@perspective-dev/viewer 5.1.0 → 5.2.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 (175) hide show
  1. package/dist/cdn/perspective-viewer.js +9 -9
  2. package/dist/cdn/perspective-viewer.js.map +4 -4
  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/intl/de.css +1 -1
  8. package/dist/css/intl/es.css +1 -1
  9. package/dist/css/intl/fr.css +1 -1
  10. package/dist/css/intl/ja.css +1 -1
  11. package/dist/css/intl/pt.css +1 -1
  12. package/dist/css/intl/zh.css +1 -1
  13. package/dist/css/intl.css +1 -1
  14. package/dist/css/monokai.css +1 -1
  15. package/dist/css/phosphor.css +1 -1
  16. package/dist/css/pro-dark.css +1 -1
  17. package/dist/css/pro.css +1 -1
  18. package/dist/css/solarized-dark.css +1 -1
  19. package/dist/css/solarized.css +1 -1
  20. package/dist/css/themes.css +1 -1
  21. package/dist/css/vaporwave.css +1 -1
  22. package/dist/docs/perspective-docs.json +1 -0
  23. package/dist/esm/column-format.d.ts +19 -28
  24. package/dist/esm/perspective-viewer.d.ts +2 -0
  25. package/dist/esm/perspective-viewer.inline.js +8 -8
  26. package/dist/esm/perspective-viewer.inline.js.map +4 -4
  27. package/dist/esm/perspective-viewer.js +9 -9
  28. package/dist/esm/perspective-viewer.js.map +4 -4
  29. package/dist/esm/providers.d.ts +79 -0
  30. package/dist/esm/ts-rs/CompactDisplay.d.ts +5 -0
  31. package/dist/esm/ts-rs/CurrencyCode.d.ts +1 -0
  32. package/dist/esm/ts-rs/CurrencyDisplay.d.ts +1 -0
  33. package/dist/esm/ts-rs/CurrencyNumberFormatStyle.d.ts +8 -0
  34. package/dist/esm/ts-rs/CurrencySign.d.ts +1 -0
  35. package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +1 -0
  36. package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +54 -0
  37. package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +34 -0
  38. package/dist/esm/ts-rs/DatetimeColorMode.d.ts +1 -0
  39. package/dist/esm/ts-rs/DatetimeFormatType.d.ts +6 -0
  40. package/dist/esm/ts-rs/FormatMode.d.ts +1 -0
  41. package/dist/esm/ts-rs/FormatUnit.d.ts +1 -0
  42. package/dist/esm/ts-rs/Notation.d.ts +17 -0
  43. package/dist/esm/ts-rs/NumberFormatStyle.d.ts +18 -0
  44. package/dist/esm/ts-rs/PanelViewerConfig.d.ts +41 -1
  45. package/dist/esm/ts-rs/PluginStaticConfig.d.ts +35 -0
  46. package/dist/esm/ts-rs/RestoreOptions.d.ts +19 -0
  47. package/dist/esm/ts-rs/RoundingMode.d.ts +1 -0
  48. package/dist/esm/ts-rs/RoundingPriority.d.ts +1 -0
  49. package/dist/esm/ts-rs/SignDisplay.d.ts +1 -0
  50. package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +1 -0
  51. package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +24 -0
  52. package/dist/esm/ts-rs/SplitRollupMode.d.ts +9 -0
  53. package/dist/esm/ts-rs/StringColorMode.d.ts +1 -0
  54. package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +1 -0
  55. package/dist/esm/ts-rs/Unit.d.ts +1 -0
  56. package/dist/esm/ts-rs/UnitDisplay.d.ts +1 -0
  57. package/dist/esm/ts-rs/UnitNumberFormatStyle.d.ts +6 -0
  58. package/dist/esm/ts-rs/UseGrouping.d.ts +1 -0
  59. package/dist/esm/ts-rs/ViewerConfig.d.ts +41 -1
  60. package/dist/esm/ts-rs/ViewerConfigInitial.d.ts +175 -0
  61. package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +63 -0
  62. package/dist/esm/ts-rs/WindowSpec.d.ts +3 -2
  63. package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +7 -6
  64. package/dist/wasm/perspective-viewer.d.ts +134 -25
  65. package/dist/wasm/perspective-viewer.js +367 -124
  66. package/dist/wasm/perspective-viewer.wasm +0 -0
  67. package/dist/wasm/perspective-viewer.wasm.d.ts +18 -15
  68. package/package.json +2 -1
  69. package/src/css/_viewer_bundle.css +1 -0
  70. package/src/css/column-selector.css +8 -0
  71. package/src/css/config-selector.css +38 -3
  72. package/src/css/form/code-editor.css +2 -3
  73. package/src/css/form/mirrored-textarea.css +81 -0
  74. package/src/css/viewer.css +328 -0
  75. package/src/rust/agent/client/mod.rs +19 -0
  76. package/src/rust/agent/client/protocol.rs +320 -0
  77. package/src/rust/agent/client/transport.rs +287 -0
  78. package/src/rust/agent/client/turn.rs +174 -0
  79. package/src/rust/agent/config.rs +159 -0
  80. package/src/rust/agent/docs.rs +293 -0
  81. package/src/rust/agent/markdown/block.rs +509 -0
  82. package/src/rust/agent/markdown/entity.rs +52 -0
  83. package/src/rust/agent/markdown/events.rs +71 -0
  84. package/src/rust/agent/markdown/inline.rs +497 -0
  85. package/src/rust/agent/markdown/mod.rs +466 -0
  86. package/src/rust/agent/mod.rs +23 -0
  87. package/src/rust/agent/preamble.md +16 -0
  88. package/src/rust/agent/runtime.rs +201 -0
  89. package/src/rust/agent/slot.rs +236 -0
  90. package/src/rust/agent/tools.rs +1110 -0
  91. package/src/rust/components/chat_panel.rs +289 -0
  92. package/src/rust/components/column_selector/config_selector.rs +76 -7
  93. package/src/rust/components/column_selector.rs +7 -0
  94. package/src/rust/components/containers/dragdrop_list.rs +37 -0
  95. package/src/rust/components/form/code_editor.rs +14 -23
  96. package/src/rust/components/form/debug.rs +8 -5
  97. package/src/rust/components/form/mirrored_textarea.rs +165 -0
  98. package/src/rust/components/form/mod.rs +1 -0
  99. package/src/rust/components/mod.rs +2 -0
  100. package/src/rust/components/settings_panel.rs +80 -2
  101. package/src/rust/components/viewer/panels.rs +9 -14
  102. package/src/rust/components/viewer/render.rs +2 -0
  103. package/src/rust/components/window_editor.rs +75 -103
  104. package/src/rust/config/datetime_column_style/custom.rs +17 -0
  105. package/src/rust/config/datetime_column_style/simple.rs +10 -0
  106. package/src/rust/config/number_string_format.rs +33 -0
  107. package/src/rust/config/options.rs +18 -0
  108. package/src/rust/config/plugin_static_config.rs +120 -5
  109. package/src/rust/config/viewer_config.rs +220 -1
  110. package/src/rust/config/workspace_config.rs +7 -6
  111. package/src/rust/custom_elements/viewer.rs +209 -18
  112. package/src/rust/custom_events.rs +29 -0
  113. package/src/rust/lib.rs +13 -0
  114. package/src/rust/presentation.rs +8 -0
  115. package/src/rust/queries/get_viewer_config.rs +5 -1
  116. package/src/rust/session/column_defaults_update.rs +18 -0
  117. package/src/rust/session/metadata.rs +18 -20
  118. package/src/rust/session/replace_expression_update.rs +1 -0
  119. package/src/rust/tasks/create_panel.rs +18 -8
  120. package/src/rust/tasks/edit_window.rs +1 -1
  121. package/src/rust/tasks/restore_panel.rs +34 -17
  122. package/src/rust/tasks/sync_update_panels.rs +7 -23
  123. package/src/rust/workspace.rs +112 -20
  124. package/src/themes/intl/de.css +16 -0
  125. package/src/themes/intl/es.css +16 -0
  126. package/src/themes/intl/fr.css +16 -0
  127. package/src/themes/intl/ja.css +16 -0
  128. package/src/themes/intl/pt.css +16 -0
  129. package/src/themes/intl/zh.css +16 -0
  130. package/src/themes/intl.css +16 -0
  131. package/src/ts/column-format.ts +67 -46
  132. package/src/ts/perspective-viewer.ts +2 -0
  133. package/src/ts/providers.ts +96 -0
  134. package/src/ts/ts-rs/CompactDisplay.ts +3 -0
  135. package/src/ts/ts-rs/CurrencyCode.ts +3 -0
  136. package/src/ts/ts-rs/CurrencyDisplay.ts +3 -0
  137. package/src/ts/ts-rs/CurrencyNumberFormatStyle.ts +6 -0
  138. package/src/ts/ts-rs/CurrencySign.ts +3 -0
  139. package/src/ts/ts-rs/CustomDatetimeFormat.ts +3 -0
  140. package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +54 -0
  141. package/src/ts/ts-rs/CustomNumberFormatConfig.ts +25 -0
  142. package/src/ts/ts-rs/DatetimeColorMode.ts +3 -0
  143. package/src/ts/ts-rs/DatetimeFormatType.ts +8 -0
  144. package/src/ts/ts-rs/FormatMode.ts +3 -0
  145. package/src/ts/ts-rs/FormatUnit.ts +3 -0
  146. package/src/ts/ts-rs/Notation.ts +11 -0
  147. package/src/ts/ts-rs/NumberFormatStyle.ts +12 -0
  148. package/src/ts/ts-rs/PanelViewerConfig.ts +47 -1
  149. package/src/ts/ts-rs/PluginStaticConfig.ts +36 -1
  150. package/src/ts/ts-rs/RestoreOptions.ts +20 -0
  151. package/src/ts/ts-rs/RoundingMode.ts +3 -0
  152. package/src/ts/ts-rs/RoundingPriority.ts +3 -0
  153. package/src/ts/ts-rs/SignDisplay.ts +3 -0
  154. package/src/ts/ts-rs/SimpleDatetimeFormat.ts +3 -0
  155. package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +25 -0
  156. package/src/ts/ts-rs/SplitRollupMode.ts +11 -0
  157. package/src/ts/ts-rs/StringColorMode.ts +3 -0
  158. package/src/ts/ts-rs/TrailingZeroDisplay.ts +3 -0
  159. package/src/ts/ts-rs/Unit.ts +3 -0
  160. package/src/ts/ts-rs/UnitDisplay.ts +3 -0
  161. package/src/ts/ts-rs/UnitNumberFormatStyle.ts +5 -0
  162. package/src/ts/ts-rs/UseGrouping.ts +3 -0
  163. package/src/ts/ts-rs/ViewerConfig.ts +47 -1
  164. package/src/ts/ts-rs/ViewerConfigInitial.ts +164 -0
  165. package/src/ts/ts-rs/ViewerConfigUpdate.ts +72 -2
  166. package/src/ts/ts-rs/WindowSpec.ts +3 -2
  167. package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +7 -6
  168. package/dist/esm/ts-rs/WindowAggregate.d.ts +0 -1
  169. package/src/ts/ts-rs/WindowAggregate.ts +0 -3
  170. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-02e461f3d7062b26}/inline0.js +0 -0
  171. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-02e461f3d7062b26}/inline1.js +0 -0
  172. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-02e461f3d7062b26}/inline2.js +0 -0
  173. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-02e461f3d7062b26}/inline3.js +0 -0
  174. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-02e461f3d7062b26}/inline4.js +0 -0
  175. /package/dist/wasm/snippets/{perspective-viewer-8a8c7d5d696b43ae → perspective-viewer-02e461f3d7062b26}/inline5.js +0 -0
Binary file
@@ -27,6 +27,9 @@ export const perspectivedebugpluginelement_select_mode: (a: number, b: number) =
27
27
  export const perspectivedebugpluginelement_update: (a: number, b: number) => number;
28
28
  export const perspectiveviewerelement___get_model: (a: number) => number;
29
29
  export const perspectiveviewerelement_addPanel: (a: number, b: number) => number;
30
+ export const perspectiveviewerelement_agentConfig: (a: number, b: number, c: number) => void;
31
+ export const perspectiveviewerelement_agentPrompt: (a: number, b: number, c: number) => number;
32
+ export const perspectiveviewerelement_agentReset: (a: number) => number;
30
33
  export const perspectiveviewerelement_connectedCallback: (a: number, b: number) => void;
31
34
  export const perspectiveviewerelement_copy: (a: number, b: number) => number;
32
35
  export const perspectiveviewerelement_delete: (a: number) => number;
@@ -163,21 +166,21 @@ export const virtualdataslice_setIntegerCol: (a: number, b: number, c: number, d
163
166
  export const virtualdataslice_setStringCol: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
164
167
  export const virtualserver_handleRequest: (a: number, b: number, c: number) => number;
165
168
  export const virtualserver_new: (a: number, b: number) => void;
166
- export const __wasm_bindgen_func_elem_3667: (a: number, b: number) => void;
167
- export const __wasm_bindgen_func_elem_16364: (a: number, b: number) => void;
168
- export const __wasm_bindgen_func_elem_19409: (a: number, b: number) => void;
169
- export const __wasm_bindgen_func_elem_20067: (a: number, b: number) => void;
170
- export const __wasm_bindgen_func_elem_20096: (a: number, b: number) => void;
171
- export const __wasm_bindgen_func_elem_27549: (a: number, b: number, c: number, d: number) => void;
172
- export const __wasm_bindgen_func_elem_6430: (a: number, b: number, c: number) => void;
173
- export const __wasm_bindgen_func_elem_6431: (a: number, b: number, c: number) => void;
174
- export const __wasm_bindgen_func_elem_6432: (a: number, b: number, c: number) => void;
175
- export const __wasm_bindgen_func_elem_6428: (a: number, b: number, c: number) => void;
176
- export const __wasm_bindgen_func_elem_19529: (a: number, b: number, c: number) => void;
177
- export const __wasm_bindgen_func_elem_20072: (a: number, b: number, c: number) => void;
178
- export const __wasm_bindgen_func_elem_20113: (a: number, b: number, c: number) => void;
179
- export const __wasm_bindgen_func_elem_17084: (a: number, b: number) => number;
180
- export const __wasm_bindgen_func_elem_20071: (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;
181
184
  export const __wbindgen_export: (a: number, b: number) => number;
182
185
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
183
186
  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.1.0",
3
+ "version": "5.2.0",
4
4
  "description": "The `<perspective-viewer>` Custom Element, frontend for Perspective",
5
5
  "keywords": [
6
6
  "perspective",
@@ -69,6 +69,7 @@
69
69
  "@types/node": ">=22",
70
70
  "@types/react-dom": ">17 <20",
71
71
  "prettier": ">=3 <4",
72
+ "ts-json-schema-generator": "^2.4.0",
72
73
  "typedoc": "^0.28.7",
73
74
  "typescript": ">=5 <6",
74
75
  "zx": ">=8 <9"
@@ -35,6 +35,7 @@
35
35
  @import "render-warning.css";
36
36
  @import "status-bar.css";
37
37
 
38
+ @import "form/mirrored-textarea.css";
38
39
  @import "form/code-editor.css";
39
40
  @import "form/debug.css";
40
41
 
@@ -181,6 +181,14 @@
181
181
  border-color: var(--psp--color);
182
182
  }
183
183
 
184
+ /* Composed inside a `.pivot-column` pill (the window editor's slots),
185
+ the row's `min-width: auto` floor would hold it at content width and
186
+ overflow the container-stretched pill - collapse-to-0 requires the
187
+ definite-width chain to pass through. */
188
+ .pivot-column > .column-selector-column {
189
+ min-width: 0;
190
+ }
191
+
184
192
  .column-selector-column {
185
193
  display: flex;
186
194
  flex-direction: row-reverse;
@@ -201,12 +201,46 @@
201
201
  pointer-events: none;
202
202
  }
203
203
 
204
+ /* `--psp-label--pivot--content` is set inline by the pivot slot
205
+ * when the ACTIVE plugin declares what the field draws (a `Y Line`
206
+ * groups by its X axis; a `Treemap` by its hierarchy). The slot
207
+ * emits an intl var reference rather than words, so these labels
208
+ * localize like any other.
209
+ *
210
+ * The role leads and the field's own name follows as a secondary
211
+ * label, so the reader learns what this slot DRAWS without losing
212
+ * which config field it IS - and a plugin that declares no role
213
+ * shows just the field name, exactly as before. The slot sets
214
+ * `--psp-label--pivot-secondary--display` as a presence flag,
215
+ * since CSS cannot test whether a custom property is set. */
204
216
  #group_by label.pivot-selector-label:before {
205
- content: var(--psp-label--group-by--content, "Group By");
217
+ content: var(
218
+ --psp-label--pivot--content,
219
+ var(--psp-label--group-by--content, "Group By")
220
+ );
221
+ }
222
+
223
+ #group_by label.pivot-selector-label:after {
224
+ content: "(" var(--psp-label--group-by--content, "Group By") ")";
206
225
  }
207
226
 
208
227
  #split_by label.pivot-selector-label:before {
209
- content: var(--psp-label--split-by--content, "Split By");
228
+ content: var(
229
+ --psp-label--pivot--content,
230
+ var(--psp-label--split-by--content, "Split By")
231
+ );
232
+ }
233
+
234
+ #split_by label.pivot-selector-label:after {
235
+ content: "(" var(--psp-label--split-by--content, "Split By") ")";
236
+ }
237
+
238
+ #group_by label.pivot-selector-label:after,
239
+ #split_by label.pivot-selector-label:after {
240
+ display: var(--psp-label--pivot-secondary--display, none);
241
+ margin-left: 6px;
242
+ opacity: 0.6;
243
+ font-size: 0.9em;
210
244
  }
211
245
 
212
246
  #sort label.pivot-selector-label:before {
@@ -320,7 +354,8 @@
320
354
  }
321
355
  }
322
356
 
323
- .group_rollup_wrapper {
357
+ .group_rollup_wrapper,
358
+ .split_rollup_wrapper {
324
359
  margin-bottom: -30px;
325
360
  flex: 0 1 auto;
326
361
  color: var(--psp-inactive--color);
@@ -23,10 +23,9 @@
23
23
  height: 100px;
24
24
  }
25
25
 
26
- #editor-inner {
26
+ /* `position`/`display` come from `.mirrored-textarea`. */
27
+ .editor-inner {
27
28
  overflow: hidden;
28
- position: relative;
29
- display: flex;
30
29
  flex: 1 1 auto;
31
30
  }
32
31
 
@@ -0,0 +1,81 @@
1
+ /* ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ * ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ * ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ * ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ * ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ * ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ * ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ * ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ * ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ * ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ * ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+ */
13
+
14
+ /* Geometry for `components/form/mirrored_textarea.rs`: an invisible
15
+ * `<textarea>` stacked over a `<pre>` mirror of its text, so that layout -
16
+ * not a JS resize loop - sizes the box.
17
+ *
18
+ * This file fixes ONLY what must agree between the two layers, because
19
+ * every disagreement shows up as a caret sitting somewhere other than the
20
+ * glyphs it is between. Consumers own the rest of the box (padding,
21
+ * border, min/max size) and choose the growth axes via `white-space`. */
22
+
23
+ :host {
24
+ .mirrored-textarea {
25
+ position: relative;
26
+ display: flex;
27
+
28
+ /* Anything affecting glyph advance or line breaking must be
29
+ * identical in both layers - hence one selector, never two. */
30
+ & > .mirrored-textarea-input,
31
+ & > .mirrored-textarea-mirror {
32
+ box-sizing: border-box;
33
+ font: inherit;
34
+ letter-spacing: inherit;
35
+ line-height: inherit;
36
+ tab-size: inherit;
37
+ margin: 0;
38
+ border: none;
39
+ white-space: pre-wrap;
40
+ overflow-wrap: anywhere;
41
+ }
42
+
43
+ & > .mirrored-textarea-input {
44
+ position: absolute;
45
+ inset: 0;
46
+ width: 100%;
47
+ height: 100%;
48
+
49
+ /* The container's padding, so the two layers' text origins
50
+ * and wrap widths coincide however a consumer pads the box:
51
+ * the mirror starts at the content box, and this element
52
+ * covers the padding box and re-applies the same inset. */
53
+ padding: inherit;
54
+
55
+ resize: none;
56
+ outline: none;
57
+ overscroll-behavior: none;
58
+
59
+ /* Functional, not visual: keystrokes, selection and caret
60
+ * only. The glyphs the user reads are the mirror's. */
61
+ color: transparent;
62
+ background-color: transparent;
63
+ caret-color: var(--psp--color, #161616);
64
+ }
65
+
66
+ & > .mirrored-textarea-mirror {
67
+ /* Clicks and drags belong to the input layer above. */
68
+ pointer-events: none;
69
+ }
70
+
71
+ /* The mirror paints everything the user sees, INCLUDING the
72
+ * placeholder: a consumer supplies it as `content` on
73
+ * `.is-empty`, which the intl label mechanism can localize.
74
+ * The native `placeholder` attribute stays for assistive tech
75
+ * but is never painted - it would double up, and no stylesheet
76
+ * can translate an attribute. */
77
+ & > .mirrored-textarea-input::placeholder {
78
+ color: transparent;
79
+ }
80
+ }
81
+ }
@@ -664,6 +664,10 @@
664
664
  content: var(--psp-label--debug-tab--content);
665
665
  }
666
666
 
667
+ #chat_tabbar_tab:before {
668
+ content: var(--psp-label--chat-tab--content);
669
+ }
670
+
667
671
  label#stack-label:before {
668
672
  content: var(--psp-label--stack--content, "Stack");
669
673
  }
@@ -672,3 +676,327 @@
672
676
  content: var(--psp-label--alt-axis--content, "Alt Axis");
673
677
  }
674
678
  }
679
+
680
+ #chat_panel {
681
+ display: flex;
682
+ flex-direction: column;
683
+ flex: 1 1 auto;
684
+ min-height: 0;
685
+ min-width: 0;
686
+ contain: inline-size;
687
+ padding: 0px;
688
+ gap: 6px;
689
+
690
+ #chat_log:empty {
691
+ flex: 0 0 auto;
692
+ padding-bottom: 0px;
693
+ margin-bottom: -6px; /* offset gap */
694
+ }
695
+
696
+ #chat_log {
697
+ flex: 1 1 auto;
698
+ min-height: 0;
699
+ overflow-y: scroll;
700
+ display: flex;
701
+ flex-direction: column;
702
+ gap: 6px;
703
+ padding: 12px 6px 6px 2px;
704
+ }
705
+
706
+ .chat-message {
707
+ overflow-wrap: anywhere;
708
+ border-radius: 3px;
709
+ padding: 6px 8px;
710
+ max-width: 90%;
711
+ font-size: 1em;
712
+ }
713
+
714
+ /* User/error text is NOT markdown-rendered - preserve its whitespace. */
715
+ .chat-user,
716
+ .chat-error {
717
+ white-space: pre-wrap;
718
+ }
719
+
720
+ .chat-user {
721
+ align-self: flex-end;
722
+ background-color: var(--psp--background-color);
723
+ border: 1px solid var(--psp-inactive--color, #6e6e6e);
724
+ }
725
+
726
+ .chat-assistant {
727
+ align-self: flex-start;
728
+ background-color: #00000010;
729
+ border: 1px solid var(--psp-inactive--color, #6e6e6e);
730
+
731
+ /* Markdown content (see `agent/markdown.rs`). */
732
+ p,
733
+ ul,
734
+ ol,
735
+ blockquote,
736
+ pre,
737
+ table,
738
+ h1,
739
+ h2,
740
+ h3,
741
+ h4,
742
+ h5,
743
+ h6,
744
+ hr {
745
+ margin: 0.4em 0;
746
+
747
+ &:first-child {
748
+ margin-top: 0;
749
+ }
750
+
751
+ &:last-child {
752
+ margin-bottom: 0;
753
+ }
754
+ }
755
+
756
+ h1,
757
+ h2,
758
+ h3,
759
+ h4,
760
+ h5,
761
+ h6 {
762
+ font-size: 1.05em;
763
+ font-weight: 700;
764
+ }
765
+
766
+ ul,
767
+ ol {
768
+ padding-inline-start: 1.5em;
769
+ }
770
+
771
+ code {
772
+ font-family: inherit;
773
+ background-color: #00000028;
774
+ border-radius: 3px;
775
+ padding: 0 3px;
776
+ }
777
+
778
+ pre {
779
+ overflow-x: auto;
780
+ background-color: #00000028;
781
+ border-radius: 3px;
782
+ padding: 6px 8px;
783
+
784
+ code {
785
+ background-color: transparent;
786
+ padding: 0;
787
+ white-space: pre;
788
+ }
789
+ }
790
+
791
+ blockquote {
792
+ border-left: 2px solid var(--psp-inactive--color, #6e6e6e);
793
+ padding-left: 8px;
794
+ color: var(--psp-inactive--color, #6e6e6e);
795
+ }
796
+
797
+ hr {
798
+ border: none;
799
+ border-top: 1px solid var(--psp-inactive--color, #6e6e6e);
800
+ }
801
+
802
+ a {
803
+ color: var(--psp-active--color, #1a7da1);
804
+ }
805
+
806
+ table {
807
+ border-collapse: collapse;
808
+
809
+ th,
810
+ td {
811
+ border: 1px solid var(--psp-inactive--color, #6e6e6e);
812
+ padding: 2px 6px;
813
+ }
814
+
815
+ th {
816
+ font-weight: 700;
817
+ }
818
+ }
819
+
820
+ .chat-md-align-center {
821
+ text-align: center;
822
+ }
823
+
824
+ .chat-md-align-right {
825
+ text-align: right;
826
+ }
827
+ }
828
+
829
+ .chat-error {
830
+ align-self: flex-start;
831
+ color: var(--warning--color, #ff471e);
832
+ border: 1px dashed var(--warning--color, #ff471e);
833
+ }
834
+
835
+ .chat-tool-chip {
836
+ align-self: flex-start;
837
+ font-size: 0.66em;
838
+ text-transform: uppercase;
839
+ color: var(--psp-inactive--color, #6e6e6e);
840
+ border: 1px solid var(--psp-inactive--color, #6e6e6e);
841
+ border-radius: 3px;
842
+ padding: 1px 6px;
843
+ cursor: default;
844
+ }
845
+
846
+ .chat-tool-chip-error {
847
+ color: var(--warning--color, #ff471e);
848
+ border-color: var(--warning--color, #ff471e);
849
+ }
850
+
851
+ .chat-reasoning {
852
+ font-size: 0.9em;
853
+ color: var(--psp-inactive--color, #6e6e6e);
854
+ margin-bottom: 0.4em;
855
+
856
+ summary {
857
+ cursor: pointer;
858
+ user-select: none;
859
+ &:before {
860
+ text-transform: uppercase;
861
+ content: var(--psp-label--chat-reasoning--content);
862
+ font-size: var(--psp-label--font-size, 0.75em);
863
+ }
864
+ }
865
+
866
+ /* The BODY scrolls, not the `<details>` - the summary is the
867
+ * collapse toggle, and auto-scrolling an outer scroller to the
868
+ * bottom would carry it out of view. */
869
+ .chat-reasoning-body {
870
+ white-space: pre-wrap;
871
+ margin-top: 0.4em;
872
+ max-height: 96px;
873
+ overflow-y: auto;
874
+ }
875
+ }
876
+
877
+ .chat-pending span {
878
+ display: inline-block;
879
+ width: 4px;
880
+ height: 4px;
881
+ margin-right: 3px;
882
+ border-radius: 50%;
883
+ background-color: var(--psp-inactive--color, #6e6e6e);
884
+ animation: chat-pending-pulse 1.2s infinite ease-in-out;
885
+
886
+ &:nth-child(2) {
887
+ animation-delay: 0.2s;
888
+ }
889
+
890
+ &:nth-child(3) {
891
+ animation-delay: 0.4s;
892
+ }
893
+ }
894
+
895
+ #chat_input_row {
896
+ display: flex;
897
+ gap: 6px;
898
+ flex: 0 0 auto;
899
+ padding-right: 12px;
900
+
901
+ /* The input grows downward as it fills; the button stays anchored
902
+ * to the bottom rather than stretching with it. */
903
+ align-items: flex-end;
904
+
905
+ /* The prompt is a `MirroredTextarea` (see
906
+ * `form/mirrored-textarea.css`): it is exactly as tall as its
907
+ * text, so this wrapper owns the visible box and caps how far
908
+ * that growth goes before it scrolls instead. */
909
+ #chat_input_scroll {
910
+ flex: 1 1 auto;
911
+ min-width: 0;
912
+ display: flex;
913
+ flex-direction: column;
914
+ min-height: 40px;
915
+ max-height: 160px;
916
+ overflow-y: auto;
917
+ border: 1px solid var(--psp-inactive--color, #6e6e6e);
918
+ border-radius: 3px;
919
+
920
+ &:focus-within {
921
+ border-color: var(--psp-active--color, #1a7da1);
922
+ }
923
+
924
+ /* Fills the resting box so clicks anywhere in it reach the
925
+ * input, then grows past it with the text. */
926
+ .chat-input-box {
927
+ flex: 1 0 auto;
928
+ padding: 4px 6px;
929
+ font-size: 1em;
930
+
931
+ /* The mirror paints the text; the input layer above it is
932
+ * caret-only (`mirrored-textarea.css`). */
933
+ .mirrored-textarea-mirror {
934
+ color: inherit;
935
+
936
+ /* The placeholder, as CSS `content` so the intl
937
+ * label mechanism can localize it - the native
938
+ * `placeholder` attribute is untranslatable and is
939
+ * kept only for assistive tech. */
940
+ &.is-empty:before {
941
+ content: var(--psp-label--chat-placeholder--content);
942
+ color: var(--psp-inactive--color, #6e6e6e);
943
+ }
944
+ }
945
+
946
+ /* The wrapper is the scroller - the input must not
947
+ * scroll independently of the text it mirrors. */
948
+ .mirrored-textarea-input {
949
+ overflow: hidden;
950
+ }
951
+ }
952
+ }
953
+
954
+ button {
955
+ flex: 0 0 auto;
956
+ cursor: pointer;
957
+ font-family: inherit;
958
+ font-size: var(--label--font-size, 0.75em);
959
+ text-transform: uppercase;
960
+ color: inherit;
961
+ background-color: #00000020;
962
+ border: 1px solid var(--psp-inactive--color, #6e6e6e);
963
+ border-radius: 3px;
964
+ padding: 0 10px;
965
+
966
+ /* Matches `#chat_input`'s resting `min-height`: the row no
967
+ * longer stretches its children, so this keeps the button
968
+ * square with an empty input and anchored as it grows. */
969
+ height: 40px;
970
+ }
971
+
972
+ #chat_send_button:before {
973
+ content: var(--psp-label--chat-send--content);
974
+ }
975
+
976
+ #chat_stop_button:before {
977
+ content: var(--psp-label--chat-stop--content);
978
+ }
979
+ }
980
+
981
+ #chat_badge {
982
+ flex: 0 0 auto;
983
+ font-size: 0.66em;
984
+ color: var(--psp-inactive--color, #6e6e6e);
985
+ overflow: hidden;
986
+ white-space: nowrap;
987
+ text-overflow: ellipsis;
988
+ margin-bottom: 6px;
989
+ }
990
+ }
991
+
992
+ @keyframes chat-pending-pulse {
993
+ 0%,
994
+ 80%,
995
+ 100% {
996
+ opacity: 0.25;
997
+ }
998
+
999
+ 40% {
1000
+ opacity: 1;
1001
+ }
1002
+ }
@@ -0,0 +1,19 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ pub mod protocol;
14
+ pub mod transport;
15
+ pub mod turn;
16
+
17
+ pub use protocol::ChatMessage;
18
+ pub use transport::{AgentTransport, OnDelta};
19
+ pub use turn::{TurnError, run_turn};