@perspective-dev/viewer-datagrid 4.3.0 → 4.4.1

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 (87) hide show
  1. package/dist/cdn/perspective-viewer-datagrid.js +4 -22
  2. package/dist/cdn/perspective-viewer-datagrid.js.map +4 -4
  3. package/dist/css/perspective-viewer-datagrid-toolbar.css +1 -1
  4. package/dist/css/perspective-viewer-datagrid.css +1 -1
  5. package/dist/esm/color_utils.d.ts +22 -0
  6. package/dist/esm/custom_elements/datagrid.d.ts +5 -5
  7. package/dist/esm/data_listener/format_cell.d.ts +1 -1
  8. package/dist/esm/data_listener/formatter_cache.d.ts +1 -1
  9. package/dist/esm/data_listener/index.d.ts +3 -2
  10. package/dist/esm/event_handlers/click/edit_click.d.ts +3 -2
  11. package/dist/esm/event_handlers/click.d.ts +4 -6
  12. package/dist/esm/event_handlers/dispatch_click.d.ts +3 -2
  13. package/dist/esm/event_handlers/expand_collapse.d.ts +1 -1
  14. package/dist/esm/event_handlers/focus.d.ts +4 -5
  15. package/dist/esm/event_handlers/header_click.d.ts +5 -3
  16. package/dist/esm/event_handlers/keydown/edit_keydown.d.ts +3 -4
  17. package/dist/esm/event_handlers/select_region.d.ts +3 -1
  18. package/dist/esm/event_handlers/sort.d.ts +8 -7
  19. package/dist/esm/model/create.d.ts +1 -1
  20. package/dist/esm/perspective-viewer-datagrid.js +3 -3
  21. package/dist/esm/perspective-viewer-datagrid.js.map +4 -4
  22. package/dist/esm/plugin/activate.d.ts +1 -1
  23. package/dist/esm/plugin/column_style_controls.d.ts +1 -1
  24. package/dist/esm/style_handlers/body.d.ts +3 -3
  25. package/dist/esm/style_handlers/column_header.d.ts +4 -3
  26. package/dist/esm/style_handlers/consolidated.d.ts +3 -47
  27. package/dist/esm/style_handlers/editable.d.ts +3 -2
  28. package/dist/esm/style_handlers/focus.d.ts +4 -4
  29. package/dist/esm/style_handlers/group_header.d.ts +1 -1
  30. package/dist/esm/style_handlers/table_cell/boolean.d.ts +1 -1
  31. package/dist/esm/style_handlers/table_cell/cell_flash.d.ts +1 -1
  32. package/dist/esm/style_handlers/table_cell/datetime.d.ts +6 -2
  33. package/dist/esm/style_handlers/table_cell/numeric.d.ts +1 -1
  34. package/dist/esm/style_handlers/table_cell/row_header.d.ts +1 -1
  35. package/dist/esm/style_handlers/table_cell/string.d.ts +1 -1
  36. package/dist/esm/style_handlers/types.d.ts +0 -4
  37. package/dist/esm/types.d.ts +10 -17
  38. package/package.json +3 -5
  39. package/src/css/mitered-headers.css +64 -0
  40. package/src/css/perspective-viewer-datagrid.css +6 -0
  41. package/src/{less/pro.less → css/pro.css} +32 -31
  42. package/src/css/regular_table.css +589 -0
  43. package/src/{less/row-hover.less → css/row-hover.css} +48 -29
  44. package/src/{less/scrollbar.less → css/scrollbar.css} +16 -15
  45. package/src/{less/sub-cell-scroll.less → css/sub-cell-scroll.css} +14 -13
  46. package/src/{less/toolbar.less → css/toolbar.css} +57 -39
  47. package/src/ts/color_utils.ts +144 -16
  48. package/src/ts/custom_elements/datagrid.ts +11 -12
  49. package/src/ts/custom_elements/toolbar.ts +4 -5
  50. package/src/ts/data_listener/format_cell.ts +28 -9
  51. package/src/ts/data_listener/formatter_cache.ts +1 -1
  52. package/src/ts/data_listener/index.ts +4 -8
  53. package/src/ts/event_handlers/click/edit_click.ts +7 -6
  54. package/src/ts/event_handlers/click.ts +39 -68
  55. package/src/ts/event_handlers/dispatch_click.ts +24 -25
  56. package/src/ts/event_handlers/expand_collapse.ts +7 -7
  57. package/src/ts/event_handlers/focus.ts +38 -35
  58. package/src/ts/event_handlers/header_click.ts +101 -62
  59. package/src/ts/event_handlers/keydown/edit_keydown.ts +49 -52
  60. package/src/ts/event_handlers/select_region.ts +144 -133
  61. package/src/ts/event_handlers/sort.ts +16 -24
  62. package/src/ts/model/column_overrides.ts +13 -4
  63. package/src/ts/model/create.ts +55 -59
  64. package/src/ts/model/toolbar.ts +23 -7
  65. package/src/ts/plugin/activate.ts +120 -92
  66. package/src/ts/plugin/column_style_controls.ts +1 -1
  67. package/src/ts/plugin/save.ts +1 -0
  68. package/src/ts/style_handlers/body.ts +56 -61
  69. package/src/ts/style_handlers/column_header.ts +16 -19
  70. package/src/ts/style_handlers/consolidated.ts +22 -123
  71. package/src/ts/style_handlers/editable.ts +10 -8
  72. package/src/ts/style_handlers/focus.ts +5 -5
  73. package/src/ts/style_handlers/group_header.ts +3 -2
  74. package/src/ts/style_handlers/table_cell/boolean.ts +3 -3
  75. package/src/ts/style_handlers/table_cell/cell_flash.ts +11 -11
  76. package/src/ts/style_handlers/table_cell/datetime.ts +14 -11
  77. package/src/ts/style_handlers/table_cell/numeric.ts +24 -25
  78. package/src/ts/style_handlers/table_cell/row_header.ts +2 -2
  79. package/src/ts/style_handlers/table_cell/string.ts +20 -18
  80. package/src/ts/style_handlers/types.ts +0 -10
  81. package/src/ts/types.ts +28 -20
  82. package/dist/esm/event_handlers/deselect_all.d.ts +0 -5
  83. package/dist/esm/event_handlers/row_select_click.d.ts +0 -4
  84. package/src/less/mitered-headers.less +0 -65
  85. package/src/less/regular_table.less +0 -526
  86. package/src/ts/event_handlers/deselect_all.ts +0 -28
  87. package/src/ts/event_handlers/row_select_click.ts +0 -92
@@ -1,20 +1,21 @@
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
- // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
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
+ */
12
13
 
13
- // Scrollbar styling
14
+ /* Scrollbar styling */
14
15
  regular-table {
15
16
  outline: none;
16
17
 
17
- // webkit (chrome, safari, etc) scrollbar styling
18
+ /* webkit (chrome, safari, etc) scrollbar styling */
18
19
  &::-webkit-scrollbar,
19
20
  &::-webkit-scrollbar-corner {
20
21
  background-color: transparent;
@@ -24,8 +25,8 @@ regular-table {
24
25
 
25
26
  &::-webkit-scrollbar-thumb {
26
27
  background-clip: content-box;
27
- background: var(--icon--color);
28
- border: 5.5px solid var(--plugin--background);
28
+ background: var(--psp--color);
29
+ border: 5.5px solid var(--psp--background-color);
29
30
  max-height: 50%;
30
31
  max-width: 50%;
31
32
  min-width: 10%;
@@ -1,17 +1,18 @@
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
- // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
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
+ */
12
13
 
13
- // Handles sub-cell scrolling via CSS transform offset by variables set during
14
- // rendering.
14
+ /* Handles sub-cell scrolling via CSS transform offset by variables set during */
15
+ /* rendering. */
15
16
  perspective-viewer-datagrid:not(.sub-cell-scroll-disabled) regular-table table,
16
17
  :host(:not(.sub-cell-scroll-disabled)) regular-table table {
17
18
  tbody td,
@@ -1,14 +1,15 @@
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
- // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
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
+ */
12
13
 
13
14
  :host {
14
15
  position: relative;
@@ -42,9 +43,9 @@
42
43
 
43
44
  &:hover {
44
45
  box-shadow:
45
- -4px 0 0 var(--icon--color),
46
- 4px 0 0 var(--icon--color);
47
- background-color: var(--icon--color);
46
+ -4px 0 0 var(--psp--color),
47
+ 4px 0 0 var(--psp--color);
48
+ background-color: var(--psp--color);
48
49
  }
49
50
  }
50
51
 
@@ -54,11 +55,11 @@
54
55
  }
55
56
 
56
57
  #scroll_lock.lock-scroll:before {
57
- -webkit-mask-image: var(--toolbar-scroll-lock-active--content);
58
+ -webkit-mask-image: var(--psp-toolbar-scroll-lock-active--content);
58
59
  }
59
60
 
60
61
  #scroll_lock:before {
61
- -webkit-mask-image: var(--toolbar-scroll-lock--content);
62
+ -webkit-mask-image: var(--psp-toolbar-scroll-lock--content);
62
63
  }
63
64
 
64
65
  #select_mode:before {
@@ -70,69 +71,86 @@
70
71
  }
71
72
 
72
73
  #edit_mode[data-edit-mode="READ_ONLY"]:before {
73
- -webkit-mask-image: var(--toolbar-edit-mode--read-only--content);
74
+ -webkit-mask-image: var(--psp-toolbar-edit-mode-read-only--content);
74
75
  }
75
76
 
76
77
  #edit_mode[data-edit-mode="EDIT"]:before {
77
- -webkit-mask-image: var(--toolbar-edit-mode--edit--content);
78
+ -webkit-mask-image: var(--psp-toolbar-edit-mode-edit--content);
78
79
  }
79
80
 
80
81
  :host(.aggregated) #toolbar #edit_mode[data-edit-mode="EDIT"]:before {
81
- -webkit-mask-image: var(--toolbar-edit-mode--read-only--content);
82
+ -webkit-mask-image: var(--psp-toolbar-edit-mode-read-only--content);
82
83
  }
83
84
 
84
85
  #edit_mode[data-edit-mode="SELECT_ROW"]:before {
85
- -webkit-mask-image: var(--toolbar-edit-mode--select-row--content);
86
+ -webkit-mask-image: var(--psp-toolbar-edit-mode-select-row--content);
86
87
  }
87
88
 
88
89
  #edit_mode[data-edit-mode="SELECT_COLUMN"]:before {
89
- -webkit-mask-image: var(--toolbar-edit-mode--select-column--content);
90
+ -webkit-mask-image: var(--psp-toolbar-edit-mode-select-column--content);
90
91
  }
91
92
 
92
93
  #edit_mode[data-edit-mode="SELECT_REGION"]:before {
93
- -webkit-mask-image: var(--toolbar-edit-mode--select-region--content);
94
+ -webkit-mask-image: var(--psp-toolbar-edit-mode-select-region--content);
94
95
  }
95
96
 
96
- // #edit_mode span:before {
97
- // content: var(--edit-mode-toggle--content, "N/A");
98
- // }
97
+ #edit_mode[data-edit-mode="SELECT_ROW_TREE"]:before {
98
+ -webkit-mask-image: var(--psp-toolbar-edit-mode-select-row-tree--content);
99
+ }
100
+
101
+ /* #edit_mode span:before { */
102
+ /* content: var(--edit-mode-toggle--content, "N/A"); */
103
+ /* } */
99
104
 
100
105
  #edit_mode[data-edit-mode="READ_ONLY"] span:before {
101
- content: var(--edit-mode--read-only--content, "Read Only");
106
+ content: var(--psp-label--edit-mode-read-only--content, "Read Only");
102
107
  }
103
108
 
104
109
  #edit_mode[data-edit-mode="EDIT"] span:before {
105
- content: var(--edit-mode--edit--content, "Editable");
110
+ content: var(--psp-label--edit-mode-edit--content, "Editable");
106
111
  }
107
112
 
108
113
  #edit_mode[data-edit-mode="SELECT_ROW"] span:before {
109
- content: var(--edit-mode--select-row--content, "Row Select");
114
+ content: var(--psp-label--edit-mode-select-row--content, "Row Select");
110
115
  }
111
116
 
112
117
  #edit_mode[data-edit-mode="SELECT_COLUMN"] span:before {
113
- content: var(--edit-mode--select-column--content, "Column Select");
118
+ content: var(
119
+ --psp-label--edit-mode-select-column--content,
120
+ "Column Select"
121
+ );
114
122
  }
115
123
 
116
124
  #edit_mode[data-edit-mode="SELECT_REGION"] span:before {
117
- content: var(--edit-mode--select-region--content, "Region Select");
125
+ content: var(
126
+ --psp-label--edit-mode-select-region--content,
127
+ "Region Select"
128
+ );
129
+ }
130
+
131
+ #edit_mode[data-edit-mode="SELECT_ROW_TREE"] span:before {
132
+ content: var(
133
+ --psp-label--edit-mode-select-row-tree--content,
134
+ "Tree Select"
135
+ );
118
136
  }
119
137
 
120
138
  #scroll_lock span:before {
121
- content: var(--scroll-lock-toggle--content, "Free Scroll");
139
+ content: var(--psp-label--scroll-lock-toggle--content, "Free Scroll");
122
140
  }
123
141
 
124
142
  #scroll_lock.lock-scroll span:before {
125
- content: var(--scroll-lock-alt-toggle--content, "Align Scroll");
143
+ content: var(--psp-label--scroll-lock-alt-toggle--content, "Align Scroll");
126
144
  }
127
145
 
128
- // The icon.
146
+ /* The icon. */
129
147
  .button:before {
130
148
  width: 21px;
131
149
  height: 21px;
132
150
  content: "";
133
151
  -webkit-mask-size: cover;
134
152
  mask-size: cover;
135
- background-color: var(--icon--color);
153
+ background-color: var(--psp--color);
136
154
  }
137
155
 
138
156
  .button.editable:before,
@@ -167,8 +185,8 @@
167
185
  .hover-target:focus-within .button,
168
186
  .hover-target:hover .button {
169
187
  position: relative;
170
- background-color: var(--icon--color);
171
- color: var(--plugin--background);
188
+ background-color: var(--psp--color);
189
+ color: var(--psp--background-color);
172
190
  opacity: 1;
173
191
  display: flex;
174
192
  align-items: center;
@@ -177,10 +195,10 @@
177
195
 
178
196
  .hover-target:focus-within .button:before,
179
197
  .hover-target:hover .button:before {
180
- background-color: var(--plugin--background);
198
+ background-color: var(--psp--background-color);
181
199
  }
182
200
 
183
- // The label.
201
+ /* The label. */
184
202
  .hover-target:focus-within .button > span,
185
203
  .hover-target:hover .button > span {
186
204
  display: block;
@@ -194,7 +212,7 @@
194
212
  white-space: pre-wrap;
195
213
  line-height: 1;
196
214
  font-size: 9px;
197
- background-color: var(--icon--color);
215
+ background-color: var(--psp--color);
198
216
  width: 35px;
199
217
  text-align: center;
200
218
  border-radius: 0 0 3px 3px;
@@ -10,15 +10,145 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
- import chroma from "chroma-js";
14
13
  import type { ColorRecord } from "./types.js";
15
14
 
15
+ /** 8-bit sRGB color as `[r, g, b]` with each channel in `[0, 255]`. */
16
+ export type RGB = [number, number, number];
17
+
18
+ /** HSL color as `[h, s, l]` with `h` in degrees `[0, 360)` and `s`, `l` in `[0, 1]`. */
19
+ export type HSL = [number, number, number];
20
+
21
+ const parse_cache = new Map<string, RGB>();
22
+ let parse_ctx: CanvasRenderingContext2D | null = null;
23
+
24
+ /** Parse a CSS hex color (`#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`). Returns `null` if `input` is not a hex literal. Alpha is ignored. */
25
+ function parse_hex(input: string): RGB | null {
26
+ const s = input.startsWith("#") ? input.slice(1) : input;
27
+ if (s.length === 3 || s.length === 4) {
28
+ const r = parseInt(s[0] + s[0], 16);
29
+ const g = parseInt(s[1] + s[1], 16);
30
+ const b = parseInt(s[2] + s[2], 16);
31
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b)) return [r, g, b];
32
+ } else if (s.length === 6 || s.length === 8) {
33
+ const r = parseInt(s.slice(0, 2), 16);
34
+ const g = parseInt(s.slice(2, 4), 16);
35
+ const b = parseInt(s.slice(4, 6), 16);
36
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b)) return [r, g, b];
37
+ }
38
+ return null;
39
+ }
40
+
41
+ /** Parse a CSS `rgb()` or `rgba()` functional color. Returns `null` if `input` does not match. Alpha is ignored. */
42
+ function parse_rgb_fn(input: string): RGB | null {
43
+ const m = input.match(
44
+ /^rgba?\(\s*([\d.]+)\s*[, ]\s*([\d.]+)\s*[, ]\s*([\d.]+)/i,
45
+ );
46
+ if (!m) return null;
47
+ return [
48
+ Math.round(parseFloat(m[1])),
49
+ Math.round(parseFloat(m[2])),
50
+ Math.round(parseFloat(m[3])),
51
+ ];
52
+ }
53
+
54
+ /** Fallback parser that defers to the browser by assigning `input` to a 2D canvas `fillStyle` and re-reading the normalized value. Handles named colors, `hsl()`, etc. Returns `[0, 0, 0]` if the value is invalid or no canvas context is available. */
55
+ function parse_via_canvas(input: string): RGB {
56
+ if (!parse_ctx) {
57
+ const canvas = document.createElement("canvas");
58
+ canvas.width = canvas.height = 1;
59
+ parse_ctx = canvas.getContext("2d");
60
+ }
61
+ if (!parse_ctx) return [0, 0, 0];
62
+ parse_ctx.fillStyle = "#000";
63
+ parse_ctx.fillStyle = input;
64
+ const normalized = parse_ctx.fillStyle as string;
65
+ return parse_hex(normalized) ?? parse_rgb_fn(normalized) ?? [0, 0, 0];
66
+ }
67
+
68
+ /** Parse any CSS color string into an `RGB` triple. Tries hex and `rgb()` fast paths, then falls back to a canvas-based parser for named colors, `hsl()`, etc. Results are memoized per input. */
69
+ export function parseColor(input: string): RGB {
70
+ const key = input.trim();
71
+ const cached = parse_cache.get(key);
72
+ if (cached) return cached;
73
+ const rgb = parse_hex(key) ?? parse_rgb_fn(key) ?? parse_via_canvas(key);
74
+ parse_cache.set(key, rgb);
75
+ return rgb;
76
+ }
77
+
78
+ /** Format a single channel as a clamped, zero-padded two-digit hex byte. */
79
+ function toHex(c: number): string {
80
+ const v = Math.max(0, Math.min(255, Math.round(c)));
81
+ return v.toString(16).padStart(2, "0");
82
+ }
83
+
84
+ /** Format an `RGB` triple as a `#rrggbb` hex string. Channels are clamped to `[0, 255]`. */
85
+ export function rgbToHex([r, g, b]: RGB): string {
86
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
87
+ }
88
+
89
+ /** Convert sRGB to HSL. Output `h` is in degrees `[0, 360)`; `s` and `l` are in `[0, 1]`. */
90
+ export function rgbToHsl([r, g, b]: RGB): HSL {
91
+ const rn = r / 255,
92
+ gn = g / 255,
93
+ bn = b / 255;
94
+ const max = Math.max(rn, gn, bn);
95
+ const min = Math.min(rn, gn, bn);
96
+ const l = (max + min) / 2;
97
+ const d = max - min;
98
+ let h = 0;
99
+ let s = 0;
100
+ if (d !== 0) {
101
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
102
+ if (max === rn) h = ((gn - bn) / d + (gn < bn ? 6 : 0)) * 60;
103
+ else if (max === gn) h = ((bn - rn) / d + 2) * 60;
104
+ else h = ((rn - gn) / d + 4) * 60;
105
+ }
106
+ return [h, s, l];
107
+ }
108
+
109
+ /** Convert HSL to sRGB. `h` is wrapped into `[0, 360)`; `s` and `l` are expected in `[0, 1]`. Output channels are rounded to integers in `[0, 255]`. */
110
+ export function hslToRgb([h, s, l]: HSL): RGB {
111
+ const hn = (((h % 360) + 360) % 360) / 360;
112
+ if (s === 0) {
113
+ const v = Math.round(l * 255);
114
+ return [v, v, v];
115
+ }
116
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
117
+ const p = 2 * l - q;
118
+ const f = (t: number): number => {
119
+ if (t < 0) t += 1;
120
+ if (t > 1) t -= 1;
121
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
122
+ if (t < 1 / 2) return q;
123
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
124
+ return p;
125
+ };
126
+ return [
127
+ Math.round(f(hn + 1 / 3) * 255),
128
+ Math.round(f(hn) * 255),
129
+ Math.round(f(hn - 1 / 3) * 255),
130
+ ];
131
+ }
132
+
133
+ /**
134
+ * Blend two `RGB` colors using LRGB (gamma-naive linear) interpolation,
135
+ * matching chroma-js's default `mix` mode. `f` is the weight of `b` in `[0, 1]`
136
+ * (0 returns `a`, 1 returns `b`).
137
+ */
138
+ export function mixRgb(a: RGB, b: RGB, f = 0.5): RGB {
139
+ return [
140
+ Math.round(Math.sqrt(a[0] * a[0] * (1 - f) + b[0] * b[0] * f)),
141
+ Math.round(Math.sqrt(a[1] * a[1] * (1 - f) + b[1] * b[1] * f)),
142
+ Math.round(Math.sqrt(a[2] * a[2] * (1 - f) + b[2] * b[2] * f)),
143
+ ];
144
+ }
145
+
146
+ /** 50/50 LRGB blend of CSS color `a` with `RGB`-ish triple `b`, returned as `#rrggbb`. */
16
147
  export function blend(a: string, b: number[]): string {
17
- return chroma.mix(a, `rgb(${b[0]},${b[1]},${b[2]})`, 0.5).hex();
148
+ return rgbToHex(mixRgb(parseColor(a), [b[0], b[1], b[2]], 0.5));
18
149
  }
19
150
 
20
- // AFAICT `chroma-js` has no alpha-aware blending? So we need a function to get
21
- // the color of a heatmap cell over the background.
151
+ /** Composite a premultiplied-style `RGBA` cell color over `source` (default white) and return the resulting opaque `RGB`. Used to flatten heatmap cells against the background. */
22
152
  export function rgbaToRgb(
23
153
  [r, g, b, a]: [number, number, number, number],
24
154
  source: [number, number, number] = [255, 255, 255],
@@ -30,7 +160,7 @@ export function rgbaToRgb(
30
160
  return [f(0, r), f(1, g), f(2, b)];
31
161
  }
32
162
 
33
- // Chroma does this but why bother?
163
+ /** Pick a readable foreground (`#161616` or `#ffffff`) for the given background using a perceptual luminance threshold. */
34
164
  export function infer_foreground_from_background([r, g, b]: [
35
165
  number,
36
166
  number,
@@ -42,21 +172,19 @@ export function infer_foreground_from_background([r, g, b]: [
42
172
  : "#ffffff";
43
173
  }
44
174
 
45
- function make_gradient(chromahex: chroma.Color): string {
46
- const [r, g, b] = chromahex.rgb();
47
- const [r1, g1, b1] = chromahex
48
- .set("hsl.h", (chromahex.get("hsl.h") - 15) % 360)
49
- .rgb();
50
- const [r2, g2, b2] = chromahex
51
- .set("hsl.h", (chromahex.get("hsl.h") + 15) % 360)
52
- .rgb();
175
+ /** Build a CSS `linear-gradient` that fans `rgb` ±15° in hue, used as the negative-value swatch in column color pickers. */
176
+ function make_gradient(rgb: RGB): string {
177
+ const [h, s, l] = rgbToHsl(rgb);
178
+ const [r, g, b] = rgb;
179
+ const [r1, g1, b1] = hslToRgb([h - 15, s, l]);
180
+ const [r2, g2, b2] = hslToRgb([h + 15, s, l]);
53
181
  return `linear-gradient(to right top,rgb(${r1},${g1},${b1}),rgb(${r},${g},${b}) 50%,rgb(${r2},${g2},${b2}))`;
54
182
  }
55
183
 
184
+ /** Precompute the tuple of derived color strings (RGB channels, gradient, opaque/transparent rgba) cached on the model for a configured plugin color. */
56
185
  export function make_color_record(color: string): ColorRecord {
57
- const chroma_neg = chroma(color);
58
- const _neg_grad = make_gradient(chroma_neg);
59
- const rgb = chroma_neg.rgb();
186
+ const rgb = parseColor(color);
187
+ const _neg_grad = make_gradient(rgb);
60
188
  return [
61
189
  color,
62
190
  rgb[0],
@@ -22,12 +22,14 @@ import datagridStyles from "../../../dist/css/perspective-viewer-datagrid.css";
22
22
  import { format_raw } from "../data_listener/format_cell.js";
23
23
 
24
24
  import type { View, ViewWindow } from "@perspective-dev/client";
25
- import type { IPerspectiveViewerPlugin } from "@perspective-dev/viewer";
25
+ import type {
26
+ HTMLPerspectiveViewerElement,
27
+ IPerspectiveViewerPlugin,
28
+ } from "@perspective-dev/viewer";
26
29
  import type {
27
30
  DatagridModel,
28
31
  DatagridToolbarElement,
29
32
  EditMode,
30
- PerspectiveViewerElement,
31
33
  DatagridPluginConfig,
32
34
  ColumnsConfig,
33
35
  } from "../types.js";
@@ -171,7 +173,7 @@ export class HTMLPerspectiveViewerDatagridPluginElement
171
173
  }
172
174
 
173
175
  async render(viewport?: ViewWindow): Promise<string> {
174
- const viewer = this.parentElement as PerspectiveViewerElement;
176
+ const viewer = this.parentElement as HTMLPerspectiveViewerElement;
175
177
  const view = await viewer.getView();
176
178
  const json = await view.to_columns(viewport as any);
177
179
  const cols = await view.column_paths(viewport as any);
@@ -210,7 +212,7 @@ export class HTMLPerspectiveViewerDatagridPluginElement
210
212
  return out.trim();
211
213
  }
212
214
 
213
- async resize(): Promise<void> {
215
+ async resize(_view: View): Promise<void> {
214
216
  if (!this.isConnected || this.offsetParent == null) {
215
217
  return;
216
218
  }
@@ -225,25 +227,22 @@ export class HTMLPerspectiveViewerDatagridPluginElement
225
227
  this.regular_table.clear();
226
228
  }
227
229
 
228
- async save(): Promise<any> {
230
+ save(): any {
229
231
  return save.call(this);
230
232
  }
231
233
 
232
- async restore(
233
- token: DatagridPluginConfig,
234
- columns_config?: ColumnsConfig,
235
- ): Promise<any> {
234
+ restore(token: DatagridPluginConfig, columns_config?: ColumnsConfig): void {
236
235
  return restore.call(this, token, columns_config ?? {});
237
236
  }
238
237
 
239
- async restyle(): Promise<void> {
238
+ async restyle(view: View): Promise<void> {
240
239
  // Get view from model if available, otherwise no-op
241
240
  if (this.model?._view) {
242
- await this.draw(this.model._view);
241
+ await this.draw(view);
243
242
  }
244
243
  }
245
244
 
246
- async delete(): Promise<void> {
245
+ delete(): void {
247
246
  this.disconnectedCallback();
248
247
  this._toolbar = undefined;
249
248
  if ((this.regular_table as any).table_model) {
@@ -10,12 +10,10 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
+ import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
13
14
  import TOOLBAR_STYLE from "../../../dist/css/perspective-viewer-datagrid-toolbar.css";
14
15
  import { toggle_edit_mode, toggle_scroll_lock } from "../model/toolbar.js";
15
- import type {
16
- DatagridPluginElement,
17
- PerspectiveViewerElement,
18
- } from "../types.js";
16
+ import type { DatagridPluginElement } from "../types.js";
19
17
 
20
18
  const stylesheet = new CSSStyleSheet();
21
19
  stylesheet.replaceSync(TOOLBAR_STYLE);
@@ -53,7 +51,7 @@ export class HTMLPerspectiveViewerDatagridToolbarElement extends HTMLElement {
53
51
  </div>
54
52
  `;
55
53
 
56
- const viewer = this.parentElement as PerspectiveViewerElement;
54
+ const viewer = this.parentElement as HTMLPerspectiveViewerElement;
57
55
  const plugin = this.previousElementSibling as DatagridPluginElement;
58
56
 
59
57
  plugin._scroll_lock = this.shadowRoot!.querySelector(
@@ -66,6 +64,7 @@ export class HTMLPerspectiveViewerDatagridToolbarElement extends HTMLElement {
66
64
  plugin._edit_button = this.shadowRoot!.querySelector(
67
65
  "#edit_mode",
68
66
  ) as HTMLElement;
67
+
69
68
  plugin._edit_button.addEventListener("click", () => {
70
69
  toggle_edit_mode.call(plugin);
71
70
  plugin.regular_table.draw();
@@ -12,7 +12,7 @@
12
12
 
13
13
  import { FormatterCache, Formatter } from "./formatter_cache.js";
14
14
  import type { DatagridModel, ColumnsConfig, ColumnConfig } from "../types.js";
15
- import { ColumnType } from "@perspective-dev/client";
15
+ import type { ColumnType } from "@perspective-dev/client";
16
16
 
17
17
  const FORMAT_CACHE = new FormatterCache();
18
18
  const MAX_BAR_WIDTH_PCT = 1;
@@ -44,7 +44,11 @@ export function format_cell(
44
44
  const plugin: ColumnConfig = plugins[title] || {};
45
45
  const is_numeric = type === "integer" || type === "float";
46
46
 
47
- if (is_numeric && plugin?.number_fg_mode === "bar") {
47
+ if (
48
+ is_numeric &&
49
+ (plugin?.number_fg_mode === "bar" ||
50
+ plugin?.number_fg_mode === "label-bar")
51
+ ) {
48
52
  const a = Math.max(
49
53
  0,
50
54
  Math.min(
@@ -54,15 +58,30 @@ export function format_cell(
54
58
  ),
55
59
  );
56
60
 
57
- const div = this._div_factory.get();
58
- const anchor = (val as number) >= 0 ? "left" : "right";
61
+ const anchor = (val as number) >= 0 ? "" : "justify-self:flex-end;";
59
62
  const pct = (a * 100).toFixed(2);
60
- div.setAttribute(
61
- "style",
62
- `width:calc(${pct}% - 4px);position:absolute;${anchor}:2px;height:80%;top:10%;pointer-events:none;`,
63
- );
64
63
 
65
- return div;
64
+ if (plugin.number_fg_mode === "bar") {
65
+ const div = this._div_factory.get();
66
+ div.className = "psp-bar";
67
+ div.setAttribute(
68
+ "style",
69
+ `${anchor}width:${pct}%;height:80%;top:10%;pointer-events:none;background:var(--psp-label-bar-color)`,
70
+ );
71
+
72
+ return div;
73
+ } else {
74
+ const formatter = FORMAT_CACHE.get(type, plugin);
75
+ const label = formatter ? formatter.format(val) : (val as string);
76
+
77
+ const div = this._div_factory.get();
78
+ div.className = "psp-bar";
79
+ div.setAttribute(
80
+ "style",
81
+ `--label:"${label}";${anchor}width:${pct}%;height:80%;top:10%;pointer-events:none;background:var(--psp-label-bar-color)`,
82
+ );
83
+ return div;
84
+ }
66
85
  } else if (plugin?.format === "link" && type === "string") {
67
86
  const anchor = document.createElement("a");
68
87
  anchor.setAttribute("href", val as string);
@@ -10,7 +10,7 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
- import { ColumnType } from "@perspective-dev/client";
13
+ import type { ColumnType } from "@perspective-dev/client";
14
14
  import type { ColumnConfig } from "../types.js";
15
15
 
16
16
  export interface Formatter {