@perspective-dev/viewer 5.5.1 → 5.6.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 (194) hide show
  1. package/README.md +82 -3
  2. package/dist/cdn/perspective-viewer.js +9 -9
  3. package/dist/cdn/perspective-viewer.js.map +3 -3
  4. package/dist/css/blueprint.css +1 -1
  5. package/dist/css/botanical.css +1 -1
  6. package/dist/css/dracula.css +1 -1
  7. package/dist/css/eggplant.css +1 -1
  8. package/dist/css/gruvbox-dark.css +1 -1
  9. package/dist/css/gruvbox.css +1 -1
  10. package/dist/css/icons.css +1 -1
  11. package/dist/css/intl/ar.css +1 -1
  12. package/dist/css/intl/de.css +1 -1
  13. package/dist/css/intl/es.css +1 -1
  14. package/dist/css/intl/fr.css +1 -1
  15. package/dist/css/intl/ja.css +1 -1
  16. package/dist/css/intl/pt.css +1 -1
  17. package/dist/css/intl/zh.css +1 -1
  18. package/dist/css/intl.css +1 -1
  19. package/dist/css/ledger.css +1 -1
  20. package/dist/css/monokai.css +1 -1
  21. package/dist/css/nord.css +1 -1
  22. package/dist/css/phosphor.css +1 -1
  23. package/dist/css/pro-dark.css +1 -1
  24. package/dist/css/pro.css +1 -1
  25. package/dist/css/solarized-dark.css +1 -1
  26. package/dist/css/solarized.css +1 -1
  27. package/dist/css/themes.css +1 -1
  28. package/dist/css/vaporwave.css +1 -1
  29. package/dist/css/velvet.css +1 -1
  30. package/dist/docs/perspective-docs.json +1 -1
  31. package/dist/esm/column-format.js +2 -0
  32. package/dist/esm/column-format.js.map +7 -0
  33. package/dist/esm/extensions.d.ts +3 -13
  34. package/dist/esm/perspective-viewer.d.ts +1 -1
  35. package/dist/esm/perspective-viewer.js +9 -9
  36. package/dist/esm/perspective-viewer.js.map +3 -3
  37. package/dist/esm/plugin.d.ts +4 -1
  38. package/dist/esm/select-detail.d.ts +15 -0
  39. package/dist/esm/select-detail.js +2 -0
  40. package/dist/esm/select-detail.js.map +7 -0
  41. package/dist/esm/ts-rs/DerivedTableConfig.d.ts +35 -0
  42. package/dist/esm/ts-rs/PanelViewerConfig.d.ts +7 -6
  43. package/dist/esm/ts-rs/RestoreOptions.d.ts +3 -7
  44. package/dist/esm/ts-rs/TableRef.d.ts +9 -0
  45. package/dist/esm/ts-rs/ViewerConfig.d.ts +7 -6
  46. package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +7 -5
  47. package/dist/esm/ts-rs/WorkspaceConfig.d.ts +9 -1
  48. package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +9 -0
  49. package/dist/wasm/perspective-viewer.d.ts +115 -35
  50. package/dist/wasm/perspective-viewer.js +314 -190
  51. package/dist/wasm/perspective-viewer.wasm +0 -0
  52. package/dist/wasm/perspective-viewer.wasm.d.ts +21 -17
  53. package/package.json +31 -18
  54. package/src/css/column-selector.css +205 -50
  55. package/src/css/ui/containers/context-menu.css +12 -1
  56. package/src/css/ui/containers/dropdown-menu-items.css +29 -0
  57. package/src/css/ui/containers/scroll-panel.css +4 -1
  58. package/src/rust/agent/client/protocol.rs +0 -89
  59. package/src/rust/agent/markdown/mod.rs +0 -238
  60. package/src/rust/agent/preamble.md +1 -0
  61. package/src/rust/agent/tools.rs +2 -16
  62. package/src/rust/components/column_selector/active_column.rs +15 -5
  63. package/src/rust/components/column_selector/add_expression_button.rs +9 -26
  64. package/src/rust/components/column_selector/config_selector.rs +34 -6
  65. package/src/rust/components/column_selector/derived_control.rs +229 -0
  66. package/src/rust/components/column_selector/expr_edit_button.rs +3 -2
  67. package/src/rust/components/column_selector/filter_column.rs +0 -2
  68. package/src/rust/components/column_selector/inactive_column.rs +4 -5
  69. package/src/rust/components/column_selector/pivot_column.rs +21 -1
  70. package/src/rust/components/column_selector/sort_column.rs +4 -3
  71. package/src/rust/components/column_selector.rs +21 -1
  72. package/src/rust/components/column_settings_sidebar/save_settings.rs +5 -3
  73. package/src/rust/components/column_settings_sidebar/style_tab.rs +1 -0
  74. package/src/rust/components/column_settings_sidebar.rs +25 -19
  75. package/src/rust/components/debug_panel.rs +38 -29
  76. package/src/rust/components/dragdrop_list.rs +8 -9
  77. package/src/rust/components/main_panel/msg.rs +6 -4
  78. package/src/rust/components/main_panel/reconcile.rs +6 -1
  79. package/src/rust/components/main_panel/render.rs +70 -51
  80. package/src/rust/components/main_panel/update.rs +39 -1
  81. package/src/rust/components/main_panel.rs +97 -59
  82. package/src/rust/components/new_panel_menu.rs +69 -1
  83. package/src/rust/components/panel_menu.rs +63 -12
  84. package/src/rust/components/plugin_tab.rs +3 -2
  85. package/src/rust/components/render_warning.rs +2 -1
  86. package/src/rust/components/settings_panel.rs +4 -4
  87. package/src/rust/components/status_bar.rs +74 -24
  88. package/src/rust/components/status_indicator.rs +8 -1
  89. package/src/rust/components/viewer/filters.rs +13 -1
  90. package/src/rust/components/viewer/msg.rs +4 -0
  91. package/src/rust/components/viewer/panels.rs +41 -1
  92. package/src/rust/components/viewer/render.rs +1 -0
  93. package/src/rust/components/viewer/settings.rs +0 -22
  94. package/src/rust/components/viewer/snapshots.rs +2 -2
  95. package/src/rust/components/viewer/wiring.rs +14 -0
  96. package/src/rust/components/viewer.rs +45 -25
  97. package/src/rust/components/window_editor.rs +5 -4
  98. package/src/rust/config/column_config_schema.rs +38 -377
  99. package/src/rust/config/number_string_format.rs +0 -94
  100. package/src/rust/config/options.rs +3 -7
  101. package/src/rust/config/plugin_static_config.rs +0 -42
  102. package/src/rust/config/viewer_config.rs +47 -17
  103. package/src/rust/config/workspace_config.rs +158 -128
  104. package/src/rust/custom_elements/viewer.rs +187 -131
  105. package/src/rust/custom_events.rs +33 -18
  106. package/src/rust/derived.rs +266 -0
  107. package/src/rust/exprtk/tokenize.rs +0 -54
  108. package/src/rust/js/plugin.rs +1 -1
  109. package/src/rust/lib.rs +3 -0
  110. package/src/rust/presentation.rs +23 -4
  111. package/src/rust/queries/column_locator.rs +55 -48
  112. package/src/rust/queries/get_viewer_config.rs +1 -1
  113. package/src/rust/queries/plugin_column_styles.rs +22 -23
  114. package/src/rust/renderer/dispatch.rs +2 -0
  115. package/src/rust/renderer/plugin_config.rs +652 -487
  116. package/src/rust/renderer/props.rs +4 -0
  117. package/src/rust/renderer/registry.rs +2 -6
  118. package/src/rust/renderer/state.rs +205 -0
  119. package/src/rust/renderer.rs +201 -59
  120. package/src/rust/session/metadata.rs +30 -9
  121. package/src/rust/session/op_queue.rs +430 -0
  122. package/src/rust/session/panel_state.rs +327 -0
  123. package/src/rust/session/view_subscription.rs +42 -3
  124. package/src/rust/session.rs +900 -395
  125. package/src/rust/tasks/apply_global_filters.rs +49 -35
  126. package/src/rust/tasks/auto_pause.rs +22 -12
  127. package/src/rust/tasks/copy_export.rs +5 -0
  128. package/src/rust/tasks/create_panel.rs +34 -9
  129. package/src/rust/tasks/derive.rs +312 -0
  130. package/src/rust/tasks/mod.rs +6 -2
  131. package/src/rust/tasks/pipeline.rs +145 -89
  132. package/src/rust/tasks/reset_all.rs +31 -20
  133. package/src/rust/tasks/restore_derived.rs +200 -0
  134. package/src/rust/tasks/restore_panel.rs +153 -141
  135. package/src/rust/tasks/send_column_config.rs +56 -29
  136. package/src/rust/tasks/send_plugin_config.rs +52 -23
  137. package/src/rust/tasks/set_edit_mode.rs +33 -25
  138. package/src/rust/tasks/sync_update_panels.rs +39 -12
  139. package/src/rust/tasks/table_lifecycle.rs +70 -34
  140. package/src/rust/tasks/transactional_restore.rs +387 -0
  141. package/src/rust/tasks/update_theme.rs +45 -6
  142. package/src/rust/ui/containers/scroll_panel.rs +17 -10
  143. package/src/rust/ui/containers/split_panel.rs +0 -41
  144. package/src/rust/ui/context_menu.rs +157 -18
  145. package/src/rust/ui/font_loader.rs +23 -35
  146. package/src/rust/ui/form/mirrored_textarea.rs +0 -12
  147. package/src/rust/ui/form/multi_stop_gradient_selector.rs +0 -89
  148. package/src/rust/ui/form/palette_selector.rs +0 -51
  149. package/src/rust/ui/portal.rs +4 -10
  150. package/src/rust/utils/browser/mod.rs +2 -3
  151. package/src/{ts/perspective-viewer.inline.ts → rust/utils/browser/mouse.rs} +11 -10
  152. package/src/rust/utils/browser/request_animation_frame.rs +27 -8
  153. package/src/rust/utils/css.rs +0 -360
  154. package/src/rust/utils/local_fonts.rs +0 -36
  155. package/src/rust/utils/mod.rs +2 -3
  156. package/src/rust/utils/modal_position.rs +15 -21
  157. package/src/rust/utils/{browser/tests/mod.rs → plugin_host_state.rs} +31 -1
  158. package/src/rust/utils/pubsub.rs +0 -1
  159. package/src/rust/workspace.rs +187 -140
  160. package/src/svg/derived.svg +6 -0
  161. package/src/themes/icons.css +1 -0
  162. package/src/themes/intl/ar.css +10 -0
  163. package/src/themes/intl/de.css +10 -0
  164. package/src/themes/intl/es.css +10 -0
  165. package/src/themes/intl/fr.css +10 -0
  166. package/src/themes/intl/ja.css +10 -0
  167. package/src/themes/intl/pt.css +10 -0
  168. package/src/themes/intl/zh.css +10 -0
  169. package/src/themes/intl.css +10 -0
  170. package/src/ts/extensions.ts +3 -36
  171. package/src/ts/perspective-viewer.ts +1 -1
  172. package/src/ts/plugin.ts +4 -1
  173. package/src/{rust/utils/tests/request_animation_frame.rs → ts/select-detail.ts} +32 -26
  174. package/src/ts/ts-rs/DerivedTableConfig.ts +22 -0
  175. package/src/ts/ts-rs/PanelViewerConfig.ts +7 -6
  176. package/src/ts/ts-rs/RestoreOptions.ts +3 -7
  177. package/src/ts/ts-rs/TableRef.ts +9 -0
  178. package/src/ts/ts-rs/ViewerConfig.ts +7 -6
  179. package/src/ts/ts-rs/ViewerConfigUpdate.ts +7 -5
  180. package/src/ts/ts-rs/WorkspaceConfig.ts +7 -1
  181. package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +7 -0
  182. package/dist/esm/perspective-viewer.inline.d.ts +0 -3
  183. package/dist/esm/perspective-viewer.inline.js +0 -21
  184. package/dist/esm/perspective-viewer.inline.js.map +0 -7
  185. package/src/rust/tasks/restore_and_render.rs +0 -107
  186. package/src/rust/utils/browser/tests/debounce.rs +0 -163
  187. package/src/rust/utils/tests/mod.rs +0 -14
  188. package/src/rust/utils/tests/pubsub.rs +0 -95
  189. /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline0.js +0 -0
  190. /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline1.js +0 -0
  191. /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline2.js +0 -0
  192. /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline3.js +0 -0
  193. /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline4.js +0 -0
  194. /package/dist/wasm/snippets/{perspective-viewer-6813b568219c6763 → perspective-viewer-d0d525977a1acba2}/inline5.js +0 -0
Binary file
@@ -86,16 +86,19 @@ export const client_remove_hosted_tables_update: (a: number, b: number) => numbe
86
86
  export const client_system_info: (a: number) => number;
87
87
  export const client_table: (a: number, b: number, c: number) => number;
88
88
  export const client_terminate: (a: number, b: number) => void;
89
+ export const genericsqlvirtualservermodel_expressionDescribe: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
90
+ export const genericsqlvirtualservermodel_expressionsDescribe: (a: number, b: number, c: number, d: number, e: number) => void;
89
91
  export const genericsqlvirtualservermodel_getHostedTables: (a: number, b: number) => void;
90
92
  export const genericsqlvirtualservermodel_new: (a: number, b: number) => void;
93
+ export const genericsqlvirtualservermodel_tableDescribe: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
91
94
  export const genericsqlvirtualservermodel_tableMakeView: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
92
95
  export const genericsqlvirtualservermodel_tableSchema: (a: number, b: number, c: number, d: number) => void;
93
96
  export const genericsqlvirtualservermodel_tableSize: (a: number, b: number, c: number, d: number) => void;
94
- export const genericsqlvirtualservermodel_tableValidateExpression: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
95
97
  export const genericsqlvirtualservermodel_viewColumnSize: (a: number, b: number, c: number, d: number) => void;
96
98
  export const genericsqlvirtualservermodel_viewDelete: (a: number, b: number, c: number, d: number) => void;
97
99
  export const genericsqlvirtualservermodel_viewGetData: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
98
100
  export const genericsqlvirtualservermodel_viewGetMinMax: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
101
+ export const genericsqlvirtualservermodel_viewMakeTable: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void;
99
102
  export const genericsqlvirtualservermodel_viewSchema: (a: number, b: number, c: number, d: number) => void;
100
103
  export const genericsqlvirtualservermodel_viewSize: (a: number, b: number, c: number, d: number) => void;
101
104
  export const proxysession_close: (a: number) => number;
@@ -105,6 +108,7 @@ export const table___getClassname: (a: number, b: number) => void;
105
108
  export const table_clear: (a: number) => number;
106
109
  export const table_columns: (a: number) => number;
107
110
  export const table_delete: (a: number, b: number) => number;
111
+ export const table_describe: (a: number, b: number) => number;
108
112
  export const table_get_client: (a: number) => number;
109
113
  export const table_get_index: (a: number) => number;
110
114
  export const table_get_limit: (a: number) => number;
@@ -157,22 +161,22 @@ export const virtualdataslice_setIntegerCol: (a: number, b: number, c: number, d
157
161
  export const virtualdataslice_setStringCol: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
158
162
  export const virtualserver_handleRequest: (a: number, b: number, c: number) => number;
159
163
  export const virtualserver_new: (a: number, b: number) => void;
160
- export const __wasm_bindgen_func_elem_18919: (a: number, b: number) => void;
161
- export const __wasm_bindgen_func_elem_4482: (a: number, b: number) => void;
162
- export const __wasm_bindgen_func_elem_19628: (a: number, b: number) => void;
163
- export const __wasm_bindgen_func_elem_20538: (a: number, b: number) => void;
164
- export const __wasm_bindgen_func_elem_25347: (a: number, b: number) => void;
165
- export const __wasm_bindgen_func_elem_33507: (a: number, b: number, c: number, d: number) => void;
166
- export const __wasm_bindgen_func_elem_19039: (a: number, b: number, c: number) => void;
167
- export const __wasm_bindgen_func_elem_7893: (a: number, b: number, c: number) => void;
168
- export const __wasm_bindgen_func_elem_7894: (a: number, b: number, c: number) => void;
169
- export const __wasm_bindgen_func_elem_7895: (a: number, b: number, c: number) => void;
170
- export const __wasm_bindgen_func_elem_7891: (a: number, b: number, c: number) => void;
171
- export const __wasm_bindgen_func_elem_19633: (a: number, b: number, c: number) => void;
172
- export const __wasm_bindgen_func_elem_25364: (a: number, b: number, c: number) => void;
173
- export const __wasm_bindgen_func_elem_21577: (a: number, b: number) => number;
174
- export const __wasm_bindgen_func_elem_19632: (a: number, b: number) => void;
175
- export const __wasm_bindgen_func_elem_21578: (a: number, b: number) => void;
164
+ export const __wasm_bindgen_func_elem_7435: (a: number, b: number) => void;
165
+ export const __wasm_bindgen_func_elem_20133: (a: number, b: number) => void;
166
+ export const __wasm_bindgen_func_elem_20746: (a: number, b: number) => void;
167
+ export const __wasm_bindgen_func_elem_22147: (a: number, b: number) => void;
168
+ export const __wasm_bindgen_func_elem_26709: (a: number, b: number) => void;
169
+ export const __wasm_bindgen_func_elem_35042: (a: number, b: number, c: number, d: number) => void;
170
+ export const __wasm_bindgen_func_elem_8469: (a: number, b: number, c: number) => void;
171
+ export const __wasm_bindgen_func_elem_8470: (a: number, b: number, c: number) => void;
172
+ export const __wasm_bindgen_func_elem_8471: (a: number, b: number, c: number) => void;
173
+ export const __wasm_bindgen_func_elem_8467: (a: number, b: number, c: number) => void;
174
+ export const __wasm_bindgen_func_elem_20156: (a: number, b: number, c: number) => void;
175
+ export const __wasm_bindgen_func_elem_20750: (a: number, b: number, c: number) => void;
176
+ export const __wasm_bindgen_func_elem_26711: (a: number, b: number, c: number) => void;
177
+ export const __wasm_bindgen_func_elem_22772: (a: number, b: number) => number;
178
+ export const __wasm_bindgen_func_elem_20749: (a: number, b: number) => void;
179
+ export const __wasm_bindgen_func_elem_22773: (a: number, b: number) => void;
176
180
  export const __wbindgen_export: (a: number, b: number) => number;
177
181
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
178
182
  export const __wbindgen_export3: (a: number) => void;
package/package.json CHANGED
@@ -1,19 +1,27 @@
1
1
  {
2
2
  "name": "@perspective-dev/viewer",
3
- "version": "5.5.1",
4
- "description": "The `<perspective-viewer>` Custom Element, frontend for Perspective",
3
+ "version": "5.6.0",
4
+ "description": "`<perspective-viewer>`, a WebAssembly-powered data grid, pivot table and charting Web Component for large, real-time and streaming datasets.",
5
5
  "keywords": [
6
6
  "perspective",
7
- "data",
8
- "analytics",
9
- "visualization",
10
7
  "datagrid",
8
+ "data-grid",
9
+ "pivot-table",
10
+ "pivot",
11
11
  "charts",
12
- "web-component",
12
+ "visualization",
13
+ "dashboard",
14
+ "analytics",
15
+ "bi",
16
+ "streaming",
17
+ "real-time",
13
18
  "wasm",
14
- "arrow"
19
+ "webassembly",
20
+ "arrow",
21
+ "web-component",
22
+ "custom-element"
15
23
  ],
16
- "homepage": "https://perspective.finos.org",
24
+ "homepage": "https://perspective-dev.github.io",
17
25
  "repository": {
18
26
  "type": "git",
19
27
  "url": "https://github.com/perspective-dev/perspective"
@@ -29,10 +37,15 @@
29
37
  "import": "./dist/esm/perspective-viewer.js",
30
38
  "default": "./dist/esm/perspective-viewer.js"
31
39
  },
32
- "./inline": {
33
- "types": "./dist/esm/perspective-viewer.d.ts",
34
- "import": "./dist/esm/perspective-viewer.inline.js",
35
- "default": "./dist/esm/perspective-viewer.inline.js"
40
+ "./select-detail": {
41
+ "types": "./dist/esm/select-detail.d.ts",
42
+ "import": "./dist/esm/select-detail.js",
43
+ "default": "./dist/esm/select-detail.js"
44
+ },
45
+ "./column-format": {
46
+ "types": "./dist/esm/column-format.d.ts",
47
+ "import": "./dist/esm/column-format.js",
48
+ "default": "./dist/esm/column-format.js"
36
49
  },
37
50
  "./themes": "./dist/css/themes.css",
38
51
  "./themes/*.css": "./dist/css/*.css",
@@ -54,11 +67,14 @@
54
67
  "access": "public"
55
68
  },
56
69
  "dependencies": {
70
+ "@perspective-dev/client": "^5.6.0",
57
71
  "pro_self_extracting_wasm": "0.0.9",
58
- "regular-layout": "=0.6.1",
59
- "@perspective-dev/client": "^5.5.1"
72
+ "regular-layout": "=0.6.1"
60
73
  },
61
74
  "devDependencies": {
75
+ "@perspective-dev/esbuild-plugin": "^5.6.0",
76
+ "@perspective-dev/test": "^5.6.0",
77
+ "@perspective-dev/metadata": "^5.6.0",
62
78
  "lightningcss": "^1.29.0",
63
79
  "@playwright/test": "=1.62.0",
64
80
  "@playwright/experimental-ct-react": "=1.62.0",
@@ -69,10 +85,7 @@
69
85
  "ts-json-schema-generator": "^2.4.0",
70
86
  "typedoc": "^0.28.7",
71
87
  "typescript": ">=5 <6",
72
- "zx": ">=8 <9",
73
- "@perspective-dev/test": "^5.5.1",
74
- "@perspective-dev/esbuild-plugin": "^5.5.1",
75
- "@perspective-dev/metadata": "^5.5.1"
88
+ "zx": ">=8 <9"
76
89
  },
77
90
  "scripts": {
78
91
  "build": "node ./build.mjs",
@@ -112,6 +112,7 @@
112
112
  pointer-events: none;
113
113
  }
114
114
 
115
+ &:hover,
115
116
  &.modal-target,
116
117
  &.dragdrop-hover {
117
118
  color: var(--psp--background-color);
@@ -192,66 +193,66 @@
192
193
  min-width: 0;
193
194
  }
194
195
 
195
- .column-selector-column {
196
- display: flex;
197
- flex-direction: row-reverse;
198
- align-items: center;
199
- flex: 1 1 auto;
200
-
201
- /* Expression column toolbar buttons */
202
- span.expression-edit-button,
203
- span.expression-delete-button {
204
- height: 19px;
205
- width: 21px;
206
- font-family: var(--psp-button--font-family, inherit);
207
- cursor: pointer;
208
- padding: 1.5px 2.5px 0;
209
- margin-right: 2px;
210
- margin-left: auto;
211
- border-radius: 3px;
212
- border: 1px solid transparent;
213
- &:hover,
214
- &.is-editing {
215
- background-color: var(--psp--color);
216
- .icon {
217
- background-color: var(--psp--background-color);
218
- }
196
+ /* Expression column toolbar buttons */
197
+ span.expression-edit-button,
198
+ span.expression-delete-button {
199
+ height: 19px;
200
+ width: 21px;
201
+ font-family: var(--psp-button--font-family, inherit);
202
+ cursor: pointer;
203
+ padding: 1.5px 2.5px 0;
204
+ margin-right: 2px;
205
+ margin-left: auto;
206
+ border-radius: 3px;
207
+ border: 1px solid transparent;
208
+ &:hover,
209
+ &.is-editing {
210
+ background-color: var(--psp--color);
211
+ .icon {
212
+ background-color: var(--psp--background-color);
219
213
  }
220
214
  }
215
+ }
221
216
 
222
- span.expression-edit-button.disabled {
223
- opacity: 0;
224
- pointer-events: none;
225
- }
217
+ span.expression-edit-button.disabled {
218
+ opacity: 0;
219
+ pointer-events: none;
220
+ }
226
221
 
227
- span.expression-delete-button {
228
- padding-left: 5px;
229
- margin-right: 8px;
230
- margin-left: auto;
222
+ span.expression-delete-button {
223
+ padding-left: 5px;
224
+ margin-right: 8px;
225
+ margin-left: auto;
231
226
 
232
- &:before {
233
- content: var(--column-close--content, "close");
234
- }
227
+ &:before {
228
+ content: var(--column-close--content, "close");
235
229
  }
230
+ }
236
231
 
237
- span.expression-delete-button + span.expression-edit-button {
238
- margin-left: 0px;
239
- }
232
+ span.expression-delete-button + span.expression-edit-button {
233
+ margin-left: 0px;
234
+ }
240
235
 
241
- span.expression-edit-button .icon {
242
- background-repeat: no-repeat;
243
- background-color: var(--psp--color);
244
- display: inline-block;
245
- -webkit-mask-size: cover;
246
- mask-size: cover;
247
- -webkit-mask-image: var(--psp-icon--column-settings--mask-image);
248
- mask-image: var(--psp-icon--column-settings--mask-image);
236
+ span.expression-edit-button .icon {
237
+ background-repeat: no-repeat;
238
+ background-color: var(--psp--color);
239
+ display: inline-block;
240
+ -webkit-mask-size: cover;
241
+ mask-size: cover;
242
+ -webkit-mask-image: var(--psp-icon--column-settings--mask-image);
243
+ mask-image: var(--psp-icon--column-settings--mask-image);
249
244
 
250
- &:before {
251
- content: var(--psp-icon--column-settings--mask-image);
252
- visibility: hidden;
253
- }
245
+ &:before {
246
+ content: var(--psp-icon--column-settings--mask-image);
247
+ visibility: hidden;
254
248
  }
249
+ }
250
+
251
+ .column-selector-column {
252
+ display: flex;
253
+ flex-direction: row-reverse;
254
+ align-items: center;
255
+ flex: 1 1 auto;
255
256
 
256
257
  .column-selector-draggable {
257
258
  cursor: move;
@@ -377,6 +378,7 @@
377
378
 
378
379
  #active-columns {
379
380
  display: flex;
381
+ position: relative;
380
382
  padding-bottom: 8px;
381
383
  padding-top: 6px;
382
384
  }
@@ -572,3 +574,156 @@
572
574
  }
573
575
  }
574
576
  }
577
+
578
+ :host {
579
+ #derived_stack {
580
+ display: flex;
581
+ flex-direction: column;
582
+ margin-bottom: 4px;
583
+ gap: 4px;
584
+ }
585
+
586
+ .derived_level {
587
+ display: flex;
588
+ align-items: center;
589
+ /* height: 18px; */
590
+ width: 100%;
591
+ /* padding: 0px 6px; */
592
+ color: var(--psp-inactive--color, #ababab);
593
+ /* font-size: var(--label--font-size, 0.75em); */
594
+ }
595
+
596
+ #derived_stack:before {
597
+ content: "Subqueries";
598
+ font-size: var(--label--font-size, 0.75em);
599
+ }
600
+
601
+ .derived_icon {
602
+ background-repeat: no-repeat;
603
+ background-color: var(--psp-inactive--color);
604
+ display: inline-block;
605
+ -webkit-mask-size: cover;
606
+ mask-size: cover;
607
+ flex-shrink: 0;
608
+ line-height: 0;
609
+ -webkit-mask-image: var(--psp-derived--mask-image);
610
+ mask-image: var(--psp-derived--mask-image);
611
+ &:before {
612
+ content: var(--psp-derived--mask-image);
613
+ visibility: hidden;
614
+ }
615
+ }
616
+
617
+ .is-own .derived_icon {
618
+ background-color: var(--psp--color);
619
+ }
620
+
621
+ .derived_level:hover .derived_label_wrapper {
622
+ border-color: var(--psp--color);
623
+ color: var(--psp--color);
624
+ }
625
+
626
+ .derived_level:hover .derived_icon:before {
627
+ background-color: var(--psp--color);
628
+ }
629
+
630
+ .derived_label_wrapper {
631
+ height: 24px;
632
+ border: 1px solid var(--psp-inactive--color);
633
+ border-radius: 2px;
634
+ flex: 1 1 0;
635
+ min-width: 0;
636
+ font-size: 12px;
637
+ display: flex;
638
+ align-items: center;
639
+ overflow: hidden;
640
+ padding-left: 7px;
641
+ padding-right: 4px;
642
+ gap: 6px;
643
+ }
644
+
645
+ .derived_label {
646
+ flex: 1 1 0;
647
+ width: 0;
648
+ min-width: 0;
649
+ overflow: hidden;
650
+ text-overflow: ellipsis;
651
+ white-space: nowrap;
652
+ }
653
+
654
+ .derived_consumers {
655
+ opacity: 0.6;
656
+ }
657
+
658
+ .derived_consumers::before {
659
+ content: "x";
660
+ }
661
+
662
+ .derived_snapshot::before {
663
+ content: var(
664
+ --psp-label--derived-snapshot--content,
665
+ var(--psp-missing)
666
+ );
667
+ opacity: 0.6;
668
+ }
669
+
670
+ .derived_release {
671
+ cursor: pointer;
672
+ -webkit-mask-image: var(--psp-icon--close--mask-image);
673
+ mask-image: var(--psp-icon--close--mask-image);
674
+ mask-size: cover;
675
+ background-color: currentColor;
676
+ width: 14px;
677
+ height: 14px;
678
+ flex: 0 0 14px;
679
+ margin: 0 6.5px;
680
+ }
681
+
682
+ .derived_release.disabled {
683
+ cursor: inherit;
684
+ pointer-events: none;
685
+ background-color: var(--psp-inactive--color);
686
+ }
687
+
688
+ .derived_release:hover {
689
+ color: var(--psp--color, inherit);
690
+ }
691
+
692
+ #derived_stack {
693
+ flex: 0 0 auto;
694
+ margin-top: auto;
695
+ margin-right: 0px;
696
+ padding-top: 12px;
697
+ bottom: 0px;
698
+ }
699
+
700
+ .derived_level.is-own {
701
+ color: var(--psp--color, inherit);
702
+ }
703
+
704
+ .derived_create:before {
705
+ content: var(--psp-label--derive-table--content, var(--psp-missing));
706
+ }
707
+
708
+ .derived_create {
709
+ cursor: pointer;
710
+ border-radius: 3px;
711
+ border: 1px solid var(--psp-inactive--color);
712
+ display: flex;
713
+ align-items: center;
714
+ height: 24px;
715
+ line-height: 18px;
716
+ flex-direction: row;
717
+ justify-content: center;
718
+ font-size: var(--label--font-size, 0.75em);
719
+ color: var(--psp-inactive--color);
720
+ text-transform: uppercase;
721
+ /* margin-top: 12px; */
722
+ }
723
+
724
+ .derived_create:hover {
725
+ color: var(--psp--background-color);
726
+ background-color: var(--psp--color);
727
+ border-color: var(--psp--color);
728
+ }
729
+ }
@@ -73,7 +73,8 @@
73
73
  padding-left: 12px;
74
74
  }
75
75
 
76
- &:hover > .context-menu-submenu {
76
+ &:hover > .context-menu-submenu,
77
+ & > .context-menu-submenu.open {
77
78
  display: flex;
78
79
  }
79
80
  }
@@ -94,6 +95,16 @@
94
95
  color: var(--psp--color);
95
96
  border: 1px solid var(--psp-inactive--color);
96
97
  box-shadow: var(--psp-dropdown--box-shadow);
98
+
99
+ &.flip-x {
100
+ left: auto;
101
+ right: 100%;
102
+ }
103
+
104
+ &.flip-y {
105
+ top: auto;
106
+ bottom: -1px;
107
+ }
97
108
  }
98
109
 
99
110
  .context-menu-submenu > .new-panel-menu {
@@ -59,6 +59,35 @@
59
59
  }
60
60
  }
61
61
 
62
+ .dropdown-menu-item.is-derived {
63
+ display: flex;
64
+ align-items: center;
65
+ gap: 4px;
66
+ }
67
+
68
+ .dropdown-menu-item.is-derived::before {
69
+ content: "\21B3";
70
+ opacity: 0.6;
71
+ }
72
+
73
+ .dropdown-menu-item .derived_consumers {
74
+ opacity: 0.6;
75
+ }
76
+
77
+ .dropdown-menu-item .derived_consumers::before {
78
+ content: "x";
79
+ }
80
+
81
+ .dropdown-menu-item .derived_delete {
82
+ margin-left: auto;
83
+ -webkit-mask-image: var(--psp-icon--close--mask-image);
84
+ mask-image: var(--psp-icon--close--mask-image);
85
+ mask-size: cover;
86
+ background-color: currentColor;
87
+ width: 12px;
88
+ height: 12px;
89
+ }
90
+
62
91
  .no-results {
63
92
  font-style: italic;
64
93
  padding: 6px 24px;
@@ -23,6 +23,9 @@
23
23
  }
24
24
 
25
25
  .scroll-panel-content {
26
- position: relative;
26
+ position: absolute;
27
+ width: 1px;
28
+ padding-bottom: inherit;
29
+ box-sizing: content-box;
27
30
  }
28
31
  }
@@ -229,92 +229,3 @@ impl ChunkAccumulator {
229
229
  }
230
230
  }
231
231
  }
232
-
233
- #[cfg(test)]
234
- mod tests {
235
- use super::*;
236
-
237
- fn chunk(json: &str) -> ChatChunk {
238
- serde_json::from_str(json).unwrap()
239
- }
240
-
241
- #[test]
242
- fn content_and_both_reasoning_conventions_fold() {
243
- let mut acc = ChunkAccumulator::default();
244
- acc.push(chunk(r#"{"choices":[{"delta":{"role":"assistant"}}]}"#));
245
- acc.push(chunk(
246
- r#"{"choices":[{"delta":{"reasoning_content":"th"}}]}"#,
247
- ));
248
- acc.push(chunk(r#"{"choices":[{"delta":{"reasoning":"ink"}}]}"#));
249
- acc.push(chunk(r#"{"choices":[{"delta":{"content":"Hel"}}]}"#));
250
- acc.push(chunk(
251
- r#"{"choices":[{"delta":{"content":"lo","reasoning":""}}]}"#,
252
- ));
253
- assert_eq!(acc.progress(), ("Hello", "think"));
254
- let ChatMessage::Assistant {
255
- content,
256
- tool_calls,
257
- reasoning_content,
258
- } = acc.finish()
259
- else {
260
- panic!("not assistant");
261
- };
262
-
263
- assert_eq!(content.as_deref(), Some("Hello"));
264
- assert!(tool_calls.is_empty());
265
- assert_eq!(reasoning_content.as_deref(), Some("think"));
266
- }
267
-
268
- #[test]
269
- fn fragmented_tool_arguments_accumulate_by_index() {
270
- let mut acc = ChunkAccumulator::default();
271
- acc.push(chunk(
272
- r#"{"choices":[{"delta":{"tool_calls":[
273
- {"index":0,"id":"c0","function":{"name":"get_schema","arguments":""}}]}}]}"#,
274
- ));
275
-
276
- // Index 1 opens before index 0 finishes; both argument streams
277
- // interleave.
278
- acc.push(chunk(
279
- r#"{"choices":[{"delta":{"tool_calls":[
280
- {"index":1,"id":"c1","function":{"name":"set_view_config","arguments":"{\"con"}}]}}]}"#,
281
- ));
282
-
283
- acc.push(chunk(
284
- r#"{"choices":[{"delta":{"tool_calls":[
285
- {"index":1,"function":{"arguments":"fig\":{}}"}}]}}]}"#,
286
- ));
287
-
288
- let ChatMessage::Assistant { tool_calls, .. } = acc.finish() else {
289
- panic!("not assistant");
290
- };
291
-
292
- assert_eq!(tool_calls.len(), 2);
293
- assert_eq!(tool_calls[0].id, "c0");
294
- assert_eq!(tool_calls[0].function.name, "get_schema");
295
- assert_eq!(tool_calls[1].function.arguments, "{\"config\":{}}");
296
- assert_eq!(tool_calls[1].kind, "function");
297
- }
298
-
299
- /// The display-only contract: reasoning deserializes from EITHER wire
300
- /// field but NEVER serializes back into a request.
301
- #[test]
302
- fn assistant_reasoning_reads_both_aliases_and_never_serializes() {
303
- for field in ["reasoning_content", "reasoning"] {
304
- let message: ChatMessage = serde_json::from_str(&format!(
305
- r#"{{"role":"assistant","content":"hi","{field}":"secret"}}"#
306
- ))
307
- .unwrap();
308
-
309
- let ChatMessage::Assistant {
310
- reasoning_content, ..
311
- } = &message
312
- else {
313
- panic!("not assistant");
314
- };
315
-
316
- assert_eq!(reasoning_content.as_deref(), Some("secret"));
317
- assert!(!serde_json::to_string(&message).unwrap().contains("secret"));
318
- }
319
- }
320
- }