@brightspot/ui 6.8.2 → 6.8.3-rc.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 (33) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/storybook/CHANGELOG.md +19 -0
  3. package/dist/storybook/llms-full.txt +6 -6
  4. package/dist/storybook/llms.txt +6 -6
  5. package/dist/storybook/project.json +1 -1
  6. package/package.json +1 -1
  7. package/src/legacy/tool-ui/src/Avatar.css +9 -0
  8. package/src/legacy/tool-ui/src/ContentInputGroup.css +12 -0
  9. package/src/legacy/tool-ui/src/ContentSummary.css +11 -1
  10. package/src/legacy/tool-ui/src/ContentSummary.ts +24 -0
  11. package/src/legacy/tool-ui/src/Dialog.css +15 -4
  12. package/src/legacy/tool-ui/src/Diff.css +16 -0
  13. package/src/legacy/tool-ui/src/Diff.ts +76 -45
  14. package/src/legacy/tool-ui/src/MenuView.css +9 -4
  15. package/src/legacy/tool-ui/src/ProseMirrorEnhancementMenu.css +9 -1
  16. package/src/legacy/tool-ui/src/SearchResult.css +3 -3
  17. package/src/legacy/tool-ui/src/TimedContent.css +5 -1
  18. package/src/legacy/tool-ui/src/ViewPreview.css +11 -0
  19. package/src/legacy/tool-ui/src/ViewWatchers.css +1 -1
  20. package/src/legacy/tool-ui/src/Viewers.css +10 -1
  21. package/src/legacy/tool-ui/src/main/webapp/dist/RTEProseMirror.bad66c5f4a7498accca1.js +504 -0
  22. package/src/legacy/tool-ui/src/main/webapp/dist/v4.0cdcad634e3e9cc66dd3.css +3 -0
  23. package/src/legacy/tool-ui/src/main/webapp/dist/{v4.5311585e2e77268a6386.js → v4.fe59d96d43251aa03766.js} +5 -5
  24. package/src/legacy/tool-ui/src/main/webapp/dist/v5.268d53cadab4ed4b68a8.css +140 -0
  25. package/src/legacy/tool-ui/src/main/webapp/dist/{v5.c96a164f24a2a102bde0.js → v5.3eb7662648c301f10aff.js} +5 -5
  26. package/src/legacy/tool-ui/src/main/webapp/v4/Diff.less +17 -0
  27. package/src/legacy/tool-ui/src/v5.ts +6 -0
  28. package/src/legacy/tool-ui/src/main/webapp/dist/RTEProseMirror.8773fe3756519d83608e.js +0 -504
  29. package/src/legacy/tool-ui/src/main/webapp/dist/v4.19a7871e6043c2ea6433.css +0 -3
  30. package/src/legacy/tool-ui/src/main/webapp/dist/v5.990bf181d01e0cbb18e8.css +0 -140
  31. /package/src/legacy/tool-ui/src/main/webapp/dist/{RTEProseMirror.8773fe3756519d83608e.js.LICENSE.txt → RTEProseMirror.bad66c5f4a7498accca1.js.LICENSE.txt} +0 -0
  32. /package/src/legacy/tool-ui/src/main/webapp/dist/{v4.5311585e2e77268a6386.js.LICENSE.txt → v4.fe59d96d43251aa03766.js.LICENSE.txt} +0 -0
  33. /package/src/legacy/tool-ui/src/main/webapp/dist/{v5.c96a164f24a2a102bde0.js.LICENSE.txt → v5.3eb7662648c301f10aff.js.LICENSE.txt} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [6.8.3](https://github.com/perfectsense/platform-ui/compare/v6.8.2...v6.8.3) (2026-11-06)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * account for query restriction filters in search results grid (BSP-20571) ([#410](https://github.com/perfectsense/platform-ui/issues/410)) ([81ac984](https://github.com/perfectsense/platform-ui/commit/81ac9843d0163edf3d4c986a504d87ccc4a555cf))
9
+ * add save conflict compare changes popup BSP-20655 ([#415](https://github.com/perfectsense/platform-ui/issues/415)) ([3049e0d](https://github.com/perfectsense/platform-ui/commit/3049e0db2a4bc900b2ebca8ba90e5f5f5adb978e))
10
+ * BSP-19543 keep the RTE overflow button clear of the character count ([#313](https://github.com/perfectsense/platform-ui/issues/313)) ([a1bdb3e](https://github.com/perfectsense/platform-ui/commit/a1bdb3ecc63ce4bc89eab25b1c33b420b8cad78d))
11
+ * BSP-20373 CMS UI: Modal dropdowns are positioned off-screen below 768px viewport width ([#407](https://github.com/perfectsense/platform-ui/issues/407)) ([ed1eef3](https://github.com/perfectsense/platform-ui/commit/ed1eef36e1bacc2c46a8d899e05ccbd0ce9664e3))
12
+ * BSP-20478 keep Plyr video controls inside the CMS preview frame ([#389](https://github.com/perfectsense/platform-ui/issues/389)) ([a0615a1](https://github.com/perfectsense/platform-ui/commit/a0615a1fa3c7649aab10d26c648cdcc9665d3617))
13
+ * BSP-20569 Popup Is Clipped in String Fields When Using a Rich-Text Toolbar ([#414](https://github.com/perfectsense/platform-ui/issues/414)) ([c306467](https://github.com/perfectsense/platform-ui/commit/c306467c75d6dee6da4e51ed91e84af7bbe8a5e1))
14
+ * BSP-20598 Version compare: details popup for changed rich-text enhancements never loads ([#418](https://github.com/perfectsense/platform-ui/issues/418)) ([812e684](https://github.com/perfectsense/platform-ui/commit/812e6847135822af06c5720f35430a5ea1c019b8))
15
+ * BSP-20613 Long display name makes object picker unusable ([#431](https://github.com/perfectsense/platform-ui/issues/431)) ([72a3ce8](https://github.com/perfectsense/platform-ui/commit/72a3ce80ded747c3cd3bc68ab5301f636eabf3c4))
16
+ * enable keyboard scrolling for content preview frames (BSP-18252) ([#329](https://github.com/perfectsense/platform-ui/issues/329)) ([2be27d8](https://github.com/perfectsense/platform-ui/commit/2be27d8493d979c0b17f39c38229da85dd992979))
17
+ * focus login input on page load (BSP-20356) ([#357](https://github.com/perfectsense/platform-ui/issues/357)) ([83e7bdc](https://github.com/perfectsense/platform-ui/commit/83e7bdc8b1038822cd7ea1e8a7bb9e50641ac896))
18
+ * hide avatar background behind transparent uploaded images (BSP-17436) ([#368](https://github.com/perfectsense/platform-ui/issues/368)) ([3c1215a](https://github.com/perfectsense/platform-ui/commit/3c1215a627ff8fc1f72c0456a4858f285a050ea6))
19
+ * restore content-type filter focus in fullscreen search (BSP-20245) ([#417](https://github.com/perfectsense/platform-ui/issues/417)) ([b28b02d](https://github.com/perfectsense/platform-ui/commit/b28b02da15fc1651a10b2a8fc9e3d7da564c0434))
20
+ * RTE toolbar keyboard accessibility BSP-16135 ([#326](https://github.com/perfectsense/platform-ui/issues/326)) ([82ee758](https://github.com/perfectsense/platform-ui/commit/82ee758a098e94e689cd300a96761a6667bb1521))
21
+
3
22
  ## [6.8.2](https://github.com/perfectsense/platform-ui/compare/v6.8.1...v6.8.2) (2026-11-01)
4
23
 
5
24
 
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [6.8.3](https://github.com/perfectsense/platform-ui/compare/v6.8.2...v6.8.3) (2026-11-06)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * account for query restriction filters in search results grid (BSP-20571) ([#410](https://github.com/perfectsense/platform-ui/issues/410)) ([81ac984](https://github.com/perfectsense/platform-ui/commit/81ac9843d0163edf3d4c986a504d87ccc4a555cf))
9
+ * add save conflict compare changes popup BSP-20655 ([#415](https://github.com/perfectsense/platform-ui/issues/415)) ([3049e0d](https://github.com/perfectsense/platform-ui/commit/3049e0db2a4bc900b2ebca8ba90e5f5f5adb978e))
10
+ * BSP-19543 keep the RTE overflow button clear of the character count ([#313](https://github.com/perfectsense/platform-ui/issues/313)) ([a1bdb3e](https://github.com/perfectsense/platform-ui/commit/a1bdb3ecc63ce4bc89eab25b1c33b420b8cad78d))
11
+ * BSP-20373 CMS UI: Modal dropdowns are positioned off-screen below 768px viewport width ([#407](https://github.com/perfectsense/platform-ui/issues/407)) ([ed1eef3](https://github.com/perfectsense/platform-ui/commit/ed1eef36e1bacc2c46a8d899e05ccbd0ce9664e3))
12
+ * BSP-20478 keep Plyr video controls inside the CMS preview frame ([#389](https://github.com/perfectsense/platform-ui/issues/389)) ([a0615a1](https://github.com/perfectsense/platform-ui/commit/a0615a1fa3c7649aab10d26c648cdcc9665d3617))
13
+ * BSP-20569 Popup Is Clipped in String Fields When Using a Rich-Text Toolbar ([#414](https://github.com/perfectsense/platform-ui/issues/414)) ([c306467](https://github.com/perfectsense/platform-ui/commit/c306467c75d6dee6da4e51ed91e84af7bbe8a5e1))
14
+ * BSP-20598 Version compare: details popup for changed rich-text enhancements never loads ([#418](https://github.com/perfectsense/platform-ui/issues/418)) ([812e684](https://github.com/perfectsense/platform-ui/commit/812e6847135822af06c5720f35430a5ea1c019b8))
15
+ * BSP-20613 Long display name makes object picker unusable ([#431](https://github.com/perfectsense/platform-ui/issues/431)) ([72a3ce8](https://github.com/perfectsense/platform-ui/commit/72a3ce80ded747c3cd3bc68ab5301f636eabf3c4))
16
+ * enable keyboard scrolling for content preview frames (BSP-18252) ([#329](https://github.com/perfectsense/platform-ui/issues/329)) ([2be27d8](https://github.com/perfectsense/platform-ui/commit/2be27d8493d979c0b17f39c38229da85dd992979))
17
+ * focus login input on page load (BSP-20356) ([#357](https://github.com/perfectsense/platform-ui/issues/357)) ([83e7bdc](https://github.com/perfectsense/platform-ui/commit/83e7bdc8b1038822cd7ea1e8a7bb9e50641ac896))
18
+ * hide avatar background behind transparent uploaded images (BSP-17436) ([#368](https://github.com/perfectsense/platform-ui/issues/368)) ([3c1215a](https://github.com/perfectsense/platform-ui/commit/3c1215a627ff8fc1f72c0456a4858f285a050ea6))
19
+ * restore content-type filter focus in fullscreen search (BSP-20245) ([#417](https://github.com/perfectsense/platform-ui/issues/417)) ([b28b02d](https://github.com/perfectsense/platform-ui/commit/b28b02da15fc1651a10b2a8fc9e3d7da564c0434))
20
+ * RTE toolbar keyboard accessibility BSP-16135 ([#326](https://github.com/perfectsense/platform-ui/issues/326)) ([82ee758](https://github.com/perfectsense/platform-ui/commit/82ee758a098e94e689cd300a96761a6667bb1521))
21
+
3
22
  ## [6.8.2](https://github.com/perfectsense/platform-ui/compare/v6.8.1...v6.8.2) (2026-11-01)
4
23
 
5
24
 
@@ -1,8 +1,8 @@
1
1
  # Brightspot UI
2
2
 
3
- > `@brightspot/ui` 6.8.2: Lit web components (`btu-*` tags) and a TailwindCSS v3 preset for building Brightspot CMS screens and plugins.
3
+ > `@brightspot/ui` 6.8.3-rc.1: Lit web components (`btu-*` tags) and a TailwindCSS v3 preset for building Brightspot CMS screens and plugins.
4
4
 
5
- These docs describe 6.8.2. Prefer them over what you remember about this library, because component APIs change between minor versions. For the version a project actually uses, read `node_modules/@brightspot/ui/llms.txt` in that project. Releases without that file still have their manifest at `https://cdn.jsdelivr.net/npm/@brightspot/ui@<version>/dist/custom-elements.json`.
5
+ These docs describe 6.8.3-rc.1. Prefer them over what you remember about this library, because component APIs change between minor versions. For the version a project actually uses, read `node_modules/@brightspot/ui/llms.txt` in that project. Releases without that file still have their manifest at `https://cdn.jsdelivr.net/npm/@brightspot/ui@<version>/dist/custom-elements.json`.
6
6
 
7
7
  Components render in the light DOM, not a shadow root. In HTML, use the attribute names from each component page: many differ from the JavaScript property names, for example `heading-level` for `headingLevel`.
8
8
 
@@ -52,10 +52,10 @@ The guide and component pages linked below are markdown.
52
52
 
53
53
  Each link is a plugin source file; its header comment lists the classes.
54
54
 
55
- - [Button](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.2/dist/tailwind-plugin-button.ts): Buttons communicate actions that users can take such as submit a form, begin a new task, trigger a new UI element to appear or take a new or next step in some process
56
- - [Heading](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.2/dist/tailwind-plugin-heading.ts): Headings are a combination of font-size, line-height and weight
57
- - [Scroll Shadow](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.2/dist/tailwind-plugin-scroll-shadow.ts): This plugin adds shadows to the edges of a scrollable container when the content of the container overflows
58
- - [Icon](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.2/dist/tailwind-plugin-icon.ts): Lucide icons as classes, for example `before:btu-icon before:btu-icon-heart`, plus size and gradient modifiers
55
+ - [Button](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.3-rc.1/dist/tailwind-plugin-button.ts): Buttons communicate actions that users can take such as submit a form, begin a new task, trigger a new UI element to appear or take a new or next step in some process
56
+ - [Heading](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.3-rc.1/dist/tailwind-plugin-heading.ts): Headings are a combination of font-size, line-height and weight
57
+ - [Scroll Shadow](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.3-rc.1/dist/tailwind-plugin-scroll-shadow.ts): This plugin adds shadows to the edges of a scrollable container when the content of the container overflows
58
+ - [Icon](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.3-rc.1/dist/tailwind-plugin-icon.ts): Lucide icons as classes, for example `before:btu-icon before:btu-icon-heart`, plus size and gradient modifiers
59
59
 
60
60
  ## Optional
61
61
 
@@ -1,8 +1,8 @@
1
1
  # Brightspot UI
2
2
 
3
- > `@brightspot/ui` 6.8.2: Lit web components (`btu-*` tags) and a TailwindCSS v3 preset for building Brightspot CMS screens and plugins.
3
+ > `@brightspot/ui` 6.8.3-rc.1: Lit web components (`btu-*` tags) and a TailwindCSS v3 preset for building Brightspot CMS screens and plugins.
4
4
 
5
- These docs describe 6.8.2. Prefer them over what you remember about this library, because component APIs change between minor versions. For the version a project actually uses, read `node_modules/@brightspot/ui/llms.txt` in that project. Releases without that file still have their manifest at `https://cdn.jsdelivr.net/npm/@brightspot/ui@<version>/dist/custom-elements.json`.
5
+ These docs describe 6.8.3-rc.1. Prefer them over what you remember about this library, because component APIs change between minor versions. For the version a project actually uses, read `node_modules/@brightspot/ui/llms.txt` in that project. Releases without that file still have their manifest at `https://cdn.jsdelivr.net/npm/@brightspot/ui@<version>/dist/custom-elements.json`.
6
6
 
7
7
  Components render in the light DOM, not a shadow root. In HTML, use the attribute names from each component page: many differ from the JavaScript property names, for example `heading-level` for `headingLevel`.
8
8
 
@@ -52,10 +52,10 @@ The guide and component pages linked below are markdown.
52
52
 
53
53
  Each link is a plugin source file; its header comment lists the classes.
54
54
 
55
- - [Button](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.2/dist/tailwind-plugin-button.ts): Buttons communicate actions that users can take such as submit a form, begin a new task, trigger a new UI element to appear or take a new or next step in some process
56
- - [Heading](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.2/dist/tailwind-plugin-heading.ts): Headings are a combination of font-size, line-height and weight
57
- - [Scroll Shadow](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.2/dist/tailwind-plugin-scroll-shadow.ts): This plugin adds shadows to the edges of a scrollable container when the content of the container overflows
58
- - [Icon](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.2/dist/tailwind-plugin-icon.ts): Lucide icons as classes, for example `before:btu-icon before:btu-icon-heart`, plus size and gradient modifiers
55
+ - [Button](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.3-rc.1/dist/tailwind-plugin-button.ts): Buttons communicate actions that users can take such as submit a form, begin a new task, trigger a new UI element to appear or take a new or next step in some process
56
+ - [Heading](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.3-rc.1/dist/tailwind-plugin-heading.ts): Headings are a combination of font-size, line-height and weight
57
+ - [Scroll Shadow](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.3-rc.1/dist/tailwind-plugin-scroll-shadow.ts): This plugin adds shadows to the edges of a scrollable container when the content of the container overflows
58
+ - [Icon](https://cdn.jsdelivr.net/npm/@brightspot/ui@6.8.3-rc.1/dist/tailwind-plugin-icon.ts): Lucide icons as classes, for example `before:btu-icon before:btu-icon-heart`, plus size and gradient modifiers
59
59
 
60
60
  ## Optional
61
61
 
@@ -1 +1 @@
1
- {"generatedAt":1793577198764,"hasCustomBabel":false,"hasCustomWebpack":false,"hasStaticDirs":true,"hasStorybookEslint":true,"refCount":0,"knownPackages":{"testPackages":{"@storybook/addon-vitest":"10.2.12","@vitest/browser-playwright":"4.1.11","playwright":"1.58.2","vitest":"4.1.11"},"stylingPackages":{"tailwindcss":"^3.4.13","autoprefixer":"10.4.21"}},"hasRouterPackage":false,"packageManager":{"type":"yarn","agent":"yarn","nodeLinker":"undefined"},"preview":{"usesGlobals":true},"framework":{"name":"@storybook/web-components-vite","options":{}},"builder":"@storybook/builder-vite","renderer":"@storybook/web-components","portableStoriesFileCount":0,"applicationFileCount":6,"storybookVersion":"10.2.12","storybookVersionSpecifier":"10.2.12","language":"typescript","storybookPackages":{"@storybook/addon-themes":{"version":"10.2.12"},"@storybook/web-components-vite":{"version":"10.2.12"},"@wc-toolkit/storybook-helpers":{"version":"10.0.0"},"eslint-plugin-storybook":{"version":"10.0.7"},"storybook":{}},"addons":{"@storybook/addon-docs":{"version":"10.2.12"},"@storybook/addon-vitest":{"version":"10.2.12"}},"packageJsonType":"module"}
1
+ {"generatedAt":1793991007946,"hasCustomBabel":false,"hasCustomWebpack":false,"hasStaticDirs":true,"hasStorybookEslint":true,"refCount":0,"knownPackages":{"testPackages":{"@storybook/addon-vitest":"10.2.12","@vitest/browser-playwright":"4.1.11","playwright":"1.58.2","vitest":"4.1.11"},"stylingPackages":{"tailwindcss":"^3.4.13","autoprefixer":"10.4.21"}},"hasRouterPackage":false,"packageManager":{"type":"yarn","agent":"yarn","nodeLinker":"undefined"},"preview":{"usesGlobals":true},"framework":{"name":"@storybook/web-components-vite","options":{}},"builder":"@storybook/builder-vite","renderer":"@storybook/web-components","portableStoriesFileCount":0,"applicationFileCount":6,"storybookVersion":"10.2.12","storybookVersionSpecifier":"10.2.12","language":"typescript","storybookPackages":{"@storybook/addon-themes":{"version":"10.2.12"},"@storybook/web-components-vite":{"version":"10.2.12"},"@wc-toolkit/storybook-helpers":{"version":"10.0.0"},"eslint-plugin-storybook":{"version":"10.0.7"},"storybook":{}},"addons":{"@storybook/addon-docs":{"version":"10.2.12"},"@storybook/addon-vitest":{"version":"10.2.12"}},"packageJsonType":"module"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspot/ui",
3
- "version": "6.8.2",
3
+ "version": "6.8.3-rc.1",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "description": "A UI library for building Brightspot CMS components.",
@@ -29,3 +29,12 @@
29
29
  .ToolUserAvatar {
30
30
  @apply avatar shrink-0;
31
31
  }
32
+
33
+ /* Uploaded images can have transparency, so drop the initials and background that would show through. */
34
+ .ToolUserAvatar--image {
35
+ @apply bg-transparent hover:bg-transparent;
36
+
37
+ > span {
38
+ @apply hidden;
39
+ }
40
+ }
@@ -574,6 +574,18 @@
574
574
  @apply pointer-events-auto;
575
575
  }
576
576
 
577
+ /* A media preview in a note isn't the field's value: its seek and volume
578
+ sliders must stay usable. Locked content blocks the whole .CIG-note, so
579
+ restore the frame itself. The sliders inherit rather than force auto so
580
+ the player can still disable its hidden controls. */
581
+ .TimedContentPlayerNote-player-frame {
582
+ @apply pointer-events-auto;
583
+ }
584
+
585
+ .TimedContentPlayerNote-player-frame input[type] {
586
+ pointer-events: inherit;
587
+ }
588
+
577
589
  .CIG-note :where(a, button, [role='button'], btu-legacy-copy-to-clipboard) {
578
590
  @apply pointer-events-auto cursor-pointer;
579
591
  }
@@ -137,7 +137,7 @@ a.is-active + .ContentSummary-info {
137
137
  }
138
138
 
139
139
  .ContentSummary-preview {
140
- @apply bg-gray-100 p-1 [grid-area:preview];
140
+ @apply overflow-hidden bg-gray-100 p-1 [grid-area:preview];
141
141
  }
142
142
 
143
143
  @scope (.ContentSummary-preview) {
@@ -149,6 +149,16 @@ a.is-active + .ContentSummary-info {
149
149
  .PreviewFrame-types {
150
150
  @apply hidden;
151
151
  }
152
+
153
+ /* Size the frame to its reported content height so the wrapper scrolls it
154
+ (keyboard-accessible) instead of scrolling inside the cross-origin frame. */
155
+ & .PreviewFrame-typeDisplay {
156
+ @apply overflow-y-auto overflow-x-hidden;
157
+ }
158
+
159
+ & .PreviewFrame-typeDisplay > iframe[name^='PreviewFrame-preview'] {
160
+ @apply h-[var(--PreviewFrame-height,100%)] w-full;
161
+ }
152
162
  }
153
163
 
154
164
  @media (min-width: theme(screens.sm)) {
@@ -221,3 +221,27 @@ function iframePostMessage(node: HTMLIFrameElement) {
221
221
  )
222
222
  }
223
223
  }
224
+
225
+ // The summary preview (cross-origin, inert) reports its content height so the
226
+ // frame can be sized to it and the wrapper — not the frame — becomes the
227
+ // keyboard scroll container (see ContentSummary.css / ViewPreview.js).
228
+ window.addEventListener('message', ({ data, source }) => {
229
+ if (
230
+ typeof data !== 'object' ||
231
+ data?.type !== 'BSP.Preview.ContentSummaryHeight' ||
232
+ typeof data.height !== 'number' ||
233
+ !isFinite(data.height)
234
+ ) {
235
+ return
236
+ }
237
+ document
238
+ .querySelectorAll<HTMLIFrameElement>(
239
+ ".ContentSummary-preview iframe[name^='PreviewFrame-preview']",
240
+ )
241
+ .forEach((frame) => {
242
+ if (frame.contentWindow !== source) return
243
+ frame
244
+ .closest<HTMLElement>('.PreviewFrame-typeDisplay')
245
+ ?.style.setProperty('--PreviewFrame-height', `${data.height}px`)
246
+ })
247
+ })
@@ -89,11 +89,13 @@ dialog:modal {
89
89
  --padding: ; /* no padding for right-aligned popups. margin is necessary here. */
90
90
  @apply [margin-inline-start:auto] [transition:_display_0.3s_allow-discrete,_overlay_0.3s_allow-discrete,_opacity_0.25s_0.3s,_translate_0.25s_cubic-bezier(0.9,0,0.1,1)_0.3s] [translate:0_0] md:[inline-size:70vw] md:[margin-inline-end:0] [@starting-style]:[translate:45dvw_0];
91
91
 
92
- /* Dropdown lists inside of right-aligned modals need to be shifted over. */
92
+ /* scale/translate make this modal the containing block for fixed
93
+ dropdowns, so shift them by the modal's offset, which only exists while
94
+ it is 70vw wide (md and up). */
93
95
  .Dropdown,
94
96
  .ComboInput-list {
95
97
  &[data-tether-rx='l'] {
96
- @apply /*rtl:ignore*/ left-[calc(var(--Tether-rl)-30vw)];
98
+ @apply /*rtl:ignore*/ md:left-[calc(var(--Tether-rl)-30vw)];
97
99
  }
98
100
  }
99
101
  }
@@ -140,9 +142,11 @@ dialog:modal > .QueryField-frame > .Popup:where(:not([popover])) {
140
142
  > .Popup-content > :where(.frame.is-transitioned, .ContentSummary.is-open)
141
143
  ),
142
144
  &.PrePublish.is-visible,
145
+ &.popup-show.is-diff,
143
146
  &.popup-show[data-popup-source-class^='rte2'],
144
147
  &.popup-show[name='queryfield' i],
145
- &.popup-show:has(.Paste-popup) {
148
+ &.popup-show:has(.Paste-popup),
149
+ &.popup-show.is-diff {
146
150
  @apply before:scale-[2] before:opacity-0;
147
151
  }
148
152
 
@@ -290,6 +294,12 @@ dialog:modal > .QueryField-frame > .Popup:where(:not([popover])) {
290
294
  @apply btu-heading-4 col-start-1 flex min-w-0 content-center items-center gap-2 border-b-0 py-[.88rem] ps-6 text-gray-900;
291
295
  }
292
296
 
297
+ /* The object picker heading includes the edited object's label, which can be
298
+ long enough to push the results out of view. Block so the ellipsis renders. */
299
+ .Popup-content > .SearchWidget-title {
300
+ @apply blokk truncate;
301
+ }
302
+
293
303
  .Popup-close {
294
304
  @apply my-[.88rem] me-6 ms-2;
295
305
  }
@@ -358,7 +368,8 @@ dialog:modal > {
358
368
  .Popup[name^='contentEnhancement'],
359
369
  .Popup.ContentSummary-popup,
360
370
  .Popup[name='searchFields'],
361
- .Popup[name='edit-guide'] {
371
+ .Popup[name='edit-guide'],
372
+ .Popup.is-diff {
362
373
  @apply __modal-popup-lg;
363
374
  }
364
375
  }
@@ -42,11 +42,21 @@
42
42
  @apply w-1/2 min-w-[400px] overflow-clip bg-white;
43
43
  }
44
44
 
45
+ /* Span the diff popup content under the close button column too */
46
+ .Popup.is-diff > .Popup-content > .plugin-popup {
47
+ @apply col-span-full;
48
+ }
49
+
45
50
  /* Hide full-width "Back" bar in favor of the close popup "X" icon */
46
51
  .Diff-title {
47
52
  @apply hidden;
48
53
  }
49
54
 
55
+ /* Rich text enhancement diff popup: the body spans the dialog grid like a popup frame does */
56
+ #rtediff {
57
+ @apply col-span-full;
58
+ }
59
+
50
60
  .Diff-container {
51
61
  @apply max-h-[calc(100cqh_-_var(--page-header-h,_68px)_+_3px)] overflow-auto;
52
62
  }
@@ -278,3 +288,9 @@
278
288
  .Diff-row .CIG-label {
279
289
  @apply mb-2 text-xs font-medium text-gray-500;
280
290
  }
291
+
292
+ /* Save conflict "Compare Changes" button in the error message */
293
+ .ContentConflict-compare.Link {
294
+ /* Inline, not flex, so the underline skips the icon */
295
+ @apply ms-4 inline whitespace-nowrap before:me-1 before:align-middle before:btu-icon before:btu-icon-git-compare before:btu-icon-xs;
296
+ }
@@ -1,14 +1,63 @@
1
1
  import Cookies from 'js-cookie'
2
2
  import create from './dom/create'
3
3
  import onFind from './dom/onFind'
4
- type DiffFormPostFields = 'left' | 'right'
5
-
6
- interface DiffFormPostData extends FormData {
7
- append(
8
- name: DiffFormPostFields,
9
- value: string | Blob,
10
- fileName?: string,
11
- ): void
4
+ type DiffFormPostFields =
5
+ | 'left'
6
+ | 'right'
7
+ | 'leftLabel'
8
+ | 'rightLabel'
9
+ | 'conflictId'
10
+ | 'conflictChanges'
11
+
12
+ // Posts the given parameters to the diff page and shows the result in a popup.
13
+ async function openDiffPopup(
14
+ parameters: Partial<Record<DiffFormPostFields, string>>,
15
+ title?: string,
16
+ ) {
17
+ // Closing the diff popup if one is already open to prevent close button weirdness
18
+ $('.is-diff').popup('close')
19
+ const headers = new Headers()
20
+ const cookie = Cookies.get('bsp.csrf')
21
+
22
+ if (cookie) {
23
+ headers.append('Brightspot-CSRF', cookie)
24
+ }
25
+
26
+ const body = new FormData()
27
+
28
+ Object.entries(parameters).forEach(([name, value]) => {
29
+ if (value) body.append(name, value)
30
+ })
31
+
32
+ try {
33
+ const response = await fetch('/cms/diffRevision', {
34
+ method: 'POST',
35
+ headers,
36
+ body,
37
+ })
38
+ const itemHtml = await response.text()
39
+
40
+ document.getElementById('rtediff')?.remove()
41
+
42
+ const container = create('div')
43
+ container.id = 'rtediff'
44
+ document.body.appendChild(container)
45
+ container.innerHTML = itemHtml
46
+
47
+ // Leads the column headings so it's the one shown as the popup title.
48
+ if (title) {
49
+ const heading = create('h1')
50
+ heading.textContent = title
51
+ container.prepend(heading)
52
+ }
53
+
54
+ const jqueryContainer = $(container).popup()
55
+ // Attaching marker class to popup for cleanup if the user clicks on a clickable diff field
56
+ jqueryContainer.popup('container').addClass('is-diff')
57
+ jqueryContainer.popup('open')
58
+ } catch (err) {
59
+ console.error(err)
60
+ }
12
61
  }
13
62
 
14
63
  // Closes Diff popup when clicking title
@@ -47,43 +96,25 @@ onFind('[data-diff-state-id]', (element: HTMLElement) => {
47
96
  return
48
97
  }
49
98
 
50
- element.addEventListener('click', async (evt) => {
51
- // Closing the diff popup if one is already open to prevent close button weirdness
52
- $('.is-diff').popup('close')
53
- // If one side has no change the diffs array value can be undefined. We are checking for that here.
54
- const headers = new Headers()
55
- const cookie = Cookies.get('bsp.csrf')
56
-
57
- if (cookie) {
58
- headers.append('Brightspot-CSRF', cookie)
59
- }
60
-
61
- const body: DiffFormPostData = new FormData()
62
- body.append('left', diffLeftState)
63
- body.append('right', diffRightState)
64
-
65
- try {
66
- const response = await fetch('/cms/diffRevision', {
67
- method: 'POST',
68
- headers,
69
- body,
70
- })
71
- const itemHtml = await response.text()
72
-
73
- document.getElementById('rtediff')?.remove()
74
-
75
- const container = create('div')
76
- container.id = 'rtediff'
77
- document.body.appendChild(container)
78
- container.innerHTML = itemHtml
79
-
80
- const jqueryContainer = $(container).popup()
81
- // Attaching marker class to popup for cleanup if the user clicks on a clickable diff field
82
- jqueryContainer.popup('container').addClass('is-diff')
83
- jqueryContainer.popup('open')
84
- } catch (err) {
85
- console.error(err)
86
- }
99
+ element.addEventListener('click', () => {
100
+ openDiffPopup({ left: diffLeftState, right: diffRightState })
87
101
  })
88
102
  }
89
103
  })
104
+
105
+ // Save conflict: shows what saving again would change in the latest saved version
106
+ onFind('[data-conflict-diff-id]', (element: HTMLElement) => {
107
+ element.addEventListener('click', () => {
108
+ const { dataset } = element
109
+
110
+ openDiffPopup(
111
+ {
112
+ conflictId: dataset.conflictDiffId,
113
+ conflictChanges: dataset.conflictDiffChanges,
114
+ leftLabel: dataset.conflictDiffLeftLabel,
115
+ rightLabel: dataset.conflictDiffRightLabel,
116
+ },
117
+ element.textContent?.trim(),
118
+ )
119
+ })
120
+ })
@@ -7,14 +7,19 @@
7
7
  }
8
8
 
9
9
  .ProseMirrorToolbar {
10
+ /* Must match the word-count inset for the same icon count, or content lays out under it. */
10
11
  --ProseMirrorToolbar-rightControls: 3.75rem;
11
12
 
12
- &:has(+ .ProseMirror:focus) {
13
- @apply border-primary-600;
13
+ &[data-sidebar-icon-count='2'] {
14
+ --ProseMirrorToolbar-rightControls: 5.75rem;
14
15
  }
15
16
 
16
- &:has(.rte2-toolbar-find) {
17
- --ProseMirrorToolbar-rightControls: 5.75rem;
17
+ &[data-sidebar-icon-count='3'] {
18
+ --ProseMirrorToolbar-rightControls: 8rem;
19
+ }
20
+
21
+ &:has(+ .ProseMirror:focus) {
22
+ @apply border-primary-600;
18
23
  }
19
24
 
20
25
  > ul {
@@ -1,9 +1,17 @@
1
1
  .ProsemirrorEnhancementMenuContainer {
2
2
  @apply absolute hidden;
3
3
 
4
- &.open {
4
+ /* A popover's visibility follows its popover state, which the browser
5
+ clears when the editor is moved (e.g. into fullscreen). */
6
+ &.open:not([popover]) {
5
7
  @apply blokk;
6
8
  }
9
+
10
+ /* Top layer escapes the clipping .ProseMirrorContainer; anchor positioning
11
+ flips it above the enhancement when there is no room below. */
12
+ &:popover-open {
13
+ @apply blokk inset-auto m-0 mt-1 overflow-visible border-0 bg-transparent p-0 text-inherit [position-area:bottom_span-right] [position-try-fallbacks:flip-block,flip-inline] [position-visibility:anchors-visible];
14
+ }
7
15
  }
8
16
 
9
17
  .ProsemirrorEnhancementMenu-container {
@@ -7,7 +7,7 @@
7
7
  --pagination-h: 80px;
8
8
  --actions-button-w: 0px;
9
9
 
10
- @apply relative grid h-full w-full grid-cols-[auto_auto_auto_auto_minmax(0px,1fr)_auto_auto_var(--actions-button-w)_12px] grid-rows-[var(--search-controls-h)_minmax(0px,1fr)_var(--pagination-h)] items-center overflow-hidden bg-gray-50 [grid-area:results] [grid-template-areas:'toggle_sorts_fields_watching_._size-toggle_views_actions_.''results_results_results_results_results_results_results_results_results''limit_limit_limit_limit_pagination_pagination_pagination_pagination_pagination'];
10
+ @apply relative grid h-full w-full grid-cols-[auto_auto_auto_auto_minmax(0px,1fr)_auto_auto_var(--actions-button-w)_12px] grid-rows-[var(--search-controls-h)_minmax(0px,1fr)_var(--pagination-h)] items-center overflow-hidden bg-gray-50 [grid-area:results] [grid-template-areas:'toggle_sorts_fields_query-restrictions_._size-toggle_views_actions_.''results_results_results_results_results_results_results_results_results''limit_limit_limit_limit_pagination_pagination_pagination_pagination_pagination'];
11
11
 
12
12
  &:has(.SearchResult-pagination) {
13
13
  @apply after:absolute after:z-0 after:col-span-full after:row-[3/4] after:h-full after:w-full after:bg-white;
@@ -43,7 +43,7 @@
43
43
  .SearchResult {
44
44
  --fullscreen-button-w: calc(36px + 4px + 12px);
45
45
 
46
- @apply grid-cols-[auto_auto_auto_minmax(0px,1fr)_auto_auto_var(--actions-button-w)_var(--fullscreen-button-w)_var(--popup-close-w)] [grid-template-areas:'toggle_sorts_fields_._size-toggle_views_actions_fullscreen_close''results_results_results_results_results_results_results_results_results''limit_limit_limit_pagination_pagination_pagination_pagination_pagination_pagination'];
46
+ @apply grid-cols-[auto_auto_auto_auto_minmax(0px,1fr)_auto_auto_var(--actions-button-w)_var(--fullscreen-button-w)_var(--popup-close-w)] [grid-template-areas:'toggle_sorts_fields_query-restrictions_._size-toggle_views_actions_fullscreen_close''results_results_results_results_results_results_results_results_results_results''limit_limit_limit_pagination_pagination_pagination_pagination_pagination_pagination_pagination'];
47
47
  }
48
48
  }
49
49
 
@@ -377,7 +377,7 @@
377
377
 
378
378
  /* "Watching?" checkbox appears on some Search Widgets */
379
379
  .SearchResult-query {
380
- @apply mx-1 opacity-[var(--controls-opacity,_1)] transition-opacity [grid-area:watching];
380
+ @apply mx-1 opacity-[var(--controls-opacity,_1)] transition-opacity [grid-area:query-restrictions];
381
381
  }
382
382
 
383
383
  /* Allows image height controls */
@@ -24,13 +24,17 @@
24
24
  }
25
25
 
26
26
  .TimedContentPlayerNote-player-frame {
27
- @apply flex h-[250px] w-[350px] max-w-full items-center justify-center overflow-hidden rounded-lg border border-gray-300 bg-gray-50;
27
+ @apply flex h-[250px] w-[350px] max-w-full items-center justify-center overflow-hidden rounded-lg border border-gray-300 bg-gray-50 [container-type:size];
28
28
  }
29
29
 
30
30
  .TimedContentPlayerNote-player-frame .frame {
31
31
  @apply flex-grow;
32
32
  }
33
33
 
34
+ .TimedContentPlayerNote-player-frame video:not(:fullscreen, :fullscreen *) {
35
+ @apply max-h-[100cqh] object-contain;
36
+ }
37
+
34
38
  .TimedContentPlayerNote-player-close {
35
39
  @apply btu-button btu-button-text-hidden btu-button-outline btu-button-fill-none btu-button-gray btu-button-xs absolute -top-[34px] right-0 cursor-pointer before:btu-icon before:btu-icon-x;
36
40
  }
@@ -38,6 +38,17 @@
38
38
  @apply inset-0 z-10 size-full;
39
39
  }
40
40
 
41
+ .PreviewFrame-typeDisplay:focus {
42
+ @apply outline-none;
43
+ }
44
+
45
+ /* The wrapper is the keyboard focus + scroll target in both the edit page and
46
+ the Quick View popup. Outset outline, not an inset ring: the iframe fills the
47
+ wrapper and would paint over anything drawn inside it. */
48
+ .PreviewFrame-typeDisplay:focus-visible {
49
+ @apply outline-2 outline-offset-2 outline-primary-600;
50
+ }
51
+
41
52
  .PreviewFrame-previewToEditToggle {
42
53
  @apply me-auto mt-4 flex whitespace-nowrap;
43
54
 
@@ -56,7 +56,7 @@
56
56
  }
57
57
 
58
58
  /* Keeps default bg color on hover of non-interactive avatar */
59
- .ViewWatchers-item-avatar .ToolUserAvatar {
59
+ .ViewWatchers-item-avatar .ToolUserAvatar:not(.ToolUserAvatar--image) {
60
60
  @apply hover:bg-purple-600;
61
61
  }
62
62
 
@@ -11,7 +11,16 @@
11
11
 
12
12
  .Avatar {
13
13
  --avatar-size: theme('avatar.size.xs');
14
- @apply border-[1.5px] border-white dark:bg-[oklch(from_var(--avatar-bg-color)_calc(l_*_1.6)_c_h)];
14
+ @apply border-[1.5px] border-white;
15
+ }
16
+
17
+ .Avatar:not(.ToolUserAvatar--image) {
18
+ @apply dark:bg-[oklch(from_var(--avatar-bg-color)_calc(l_*_1.6)_c_h)];
19
+ }
20
+
21
+ /* Match the surface instead of staying transparent, so an overlapped avatar can't show through the image. */
22
+ .Avatar.ToolUserAvatar--image {
23
+ @apply bg-white;
15
24
  }
16
25
 
17
26
  &:where([data-editing], [data-locked]) .Avatar {