@brightspot/ui 6.3.5 → 6.4.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 (142) hide show
  1. package/README.md +2 -0
  2. package/dist/components/popover/Popover.d.ts +21 -0
  3. package/dist/components/popover/Popover.d.ts.map +1 -1
  4. package/dist/components/popover/Popover.js +85 -0
  5. package/dist/components/popover/Popover.js.map +1 -1
  6. package/dist/components/tabs/Tab.d.ts +1 -1
  7. package/dist/components/tabs/Tab.js +1 -1
  8. package/dist/custom-elements.json +14 -1
  9. package/dist/storybook/assets/{ActionBar.stories-CgkvHW27.js → ActionBar.stories-CyrWbZkU.js} +1 -1
  10. package/dist/storybook/assets/{ActionItem.stories-CyxwhrvR.js → ActionItem.stories-D289PqhK.js} +1 -1
  11. package/dist/storybook/assets/{AiSparkle.stories-h2LSw10e.js → AiSparkle.stories-Dej2Wktc.js} +1 -1
  12. package/dist/storybook/assets/{Avatar.stories-CQ3eFTbI.js → Avatar.stories-DGUhUkwq.js} +1 -1
  13. package/dist/storybook/assets/{AvatarGroup.stories-CIyZOd7R.js → AvatarGroup.stories-CPwRaMIK.js} +1 -1
  14. package/dist/storybook/assets/{Badge.stories-CwPkYUuY.js → Badge.stories-0KzitC2n.js} +1 -1
  15. package/dist/storybook/assets/{Banner.stories-B7AhWymc.js → Banner.stories-DNtqnXAp.js} +1 -1
  16. package/dist/storybook/assets/{Button-fLz-Mqji.js → Button-CWHtTXwM.js} +1 -1
  17. package/dist/storybook/assets/{Button.stories-Bj_cB5Tr.js → Button.stories-Bi-MajOM.js} +1 -1
  18. package/dist/storybook/assets/{ButtonGroup.stories-DMAr8q3A.js → ButtonGroup.stories-DRVCaM3T.js} +1 -1
  19. package/dist/storybook/assets/{Card.stories-CouVkvTr.js → Card.stories-Ca21MUf2.js} +1 -1
  20. package/dist/storybook/assets/{Celebrate.stories-Cai7aITx.js → Celebrate.stories-d4ouDVSf.js} +1 -1
  21. package/dist/storybook/assets/{Checkbox.stories-BTzuHih7.js → Checkbox.stories-DGYMCoPL.js} +1 -1
  22. package/dist/storybook/assets/{CircularProgress.stories-DwiMDCrW.js → CircularProgress.stories-TLUKn59S.js} +1 -1
  23. package/dist/storybook/assets/{ClipboardMixin.stories-BTzKKsAG.js → ClipboardMixin.stories-D4sLLX3A.js} +1 -1
  24. package/dist/storybook/assets/{Color-6BZIO3FS-z5x4axZs.js → Color-6BZIO3FS-DasxsVys.js} +1 -1
  25. package/dist/storybook/assets/{Colors.stories-LjQN3QJP.js → Colors.stories-BcaxhrWi.js} +1 -1
  26. package/dist/storybook/assets/{CombinedEffects.stories-CcWkxBPD.js → CombinedEffects.stories-Da1vPYog.js} +1 -1
  27. package/dist/storybook/assets/{ComponentStatesMixin-6JmalSeW.js → ComponentStatesMixin-C5-EArF-.js} +1 -1
  28. package/dist/storybook/assets/{ComponentStatesMixin.stories-wr7wl9D5.js → ComponentStatesMixin.stories-DPp1pnlh.js} +1 -1
  29. package/dist/storybook/assets/{CopyToClipboard.stories-CBL_GlzJ.js → CopyToClipboard.stories-CrYOAXIE.js} +1 -1
  30. package/dist/storybook/assets/{Debounce.stories-DDW0347e.js → Debounce.stories-OHpSSOWP.js} +1 -1
  31. package/dist/storybook/assets/{DocsRenderer-LL677BLK-LHrG4h5r.js → DocsRenderer-LL677BLK-BBjqnKJz.js} +3 -3
  32. package/dist/storybook/assets/{Dropdown.stories-BixGKdVC.js → Dropdown.stories-Ca_3OzYk.js} +1 -1
  33. package/dist/storybook/assets/{EmptyState.stories-DYCizkT5.js → EmptyState.stories-IJOBvkeQ.js} +1 -1
  34. package/dist/storybook/assets/{EscaAvatar.stories-IV0FybUu.js → EscaAvatar.stories-Ca5mrHK5.js} +1 -1
  35. package/dist/storybook/assets/{Events.stories-9X1B5LFU.js → Events.stories-mk3o4H-1.js} +1 -1
  36. package/dist/storybook/assets/{Heading.stories-BWFKyeYP.js → Heading.stories-BCmCdDGL.js} +1 -1
  37. package/dist/storybook/assets/{HueRipple.stories-KJySD4yc.js → HueRipple.stories-DFtimmD-.js} +1 -1
  38. package/dist/storybook/assets/{Icon.stories-n4-_RBwe.js → Icon.stories-CfsBM1vA.js} +1 -1
  39. package/dist/storybook/assets/{IconButton.stories--cc9Az0q.js → IconButton.stories-BqMbwr3s.js} +1 -1
  40. package/dist/storybook/assets/{LinearProgress.stories-CXISMQqr.js → LinearProgress.stories-BWdemzi0.js} +1 -1
  41. package/dist/storybook/assets/{Message.stories-DCgZ9H2r.js → Message.stories-Z_H9PmGg.js} +1 -1
  42. package/dist/storybook/assets/{OnFindMixin.stories-DwYEl4q4.js → OnFindMixin.stories-DmCtF_Py.js} +1 -1
  43. package/dist/storybook/assets/{Pagination.stories-B8AqV3jI.js → Pagination.stories-BbiH-XdZ.js} +1 -1
  44. package/dist/storybook/assets/{Popover.stories-Dj8TUysk.js → Popover.stories-bxWb2l8c.js} +97 -14
  45. package/dist/storybook/assets/{ReadyMixin-B1y8EBLz.js → ReadyMixin-DehOcbYB.js} +1 -1
  46. package/dist/storybook/assets/{RovingTabindexMixin.stories-BTYV78Cy.js → RovingTabindexMixin.stories-PDi3Gbmt.js} +1 -1
  47. package/dist/storybook/assets/{Rtc.stories-CiQ4OgEf.js → Rtc.stories-fVPUs7VO.js} +1 -1
  48. package/dist/storybook/assets/{ScrollShadow.stories-BRpbl9WU.js → ScrollShadow.stories-D7MTe49h.js} +1 -1
  49. package/dist/storybook/assets/{Switch.stories-Dfw56-LB.js → Switch.stories-_Xgp_9V4.js} +1 -1
  50. package/dist/storybook/assets/{Tab.stories-DCIPSPwr.js → Tab.stories-DgO_oZX0.js} +4 -4
  51. package/dist/storybook/assets/{Tabs.stories-DrT2D2oW.js → Tabs.stories-ChN1szFL.js} +1 -1
  52. package/dist/storybook/assets/{Throttle.stories-B5Y8K9s3.js → Throttle.stories-ClFkiAMe.js} +1 -1
  53. package/dist/storybook/assets/{Tooltip.stories-CUjm8cuW.js → Tooltip.stories-BHOdZEw2.js} +1 -1
  54. package/dist/storybook/assets/{Upload.stories-Dt7V8qIe.js → Upload.stories-BLs0X2F6.js} +1 -1
  55. package/dist/storybook/assets/{UploadItem.stories-DSXxGs8M.js → UploadItem.stories-CHCpPL7t.js} +1 -1
  56. package/dist/storybook/assets/{Welcome.stories-BDFQb8oF.js → Welcome.stories-DLoiQCnZ.js} +1 -1
  57. package/dist/storybook/assets/{Widget.stories-CQnE1dST.js → Widget.stories-Bk4jjx7Q.js} +1 -1
  58. package/dist/storybook/assets/{WithTooltip-65CFNBJE-D1OYJPzp.js → WithTooltip-65CFNBJE-Ckgk7wzk.js} +1 -1
  59. package/dist/storybook/assets/{blocks-Z0quNc1U.js → blocks-wSKOBuKH.js} +5 -5
  60. package/dist/storybook/assets/{formatter-EIJCOSYU-DwWzDvJC.js → formatter-EIJCOSYU-DEpJ5Gq0.js} +1 -1
  61. package/dist/storybook/assets/if-defined-DphVHb7j.js +1 -0
  62. package/dist/storybook/assets/{iframe-WTEmYHJj.js → iframe-BSHPpSig.js} +4 -4
  63. package/dist/storybook/assets/iframe-D7jBrFjV.css +1 -0
  64. package/dist/storybook/assets/{index-BvPCa7_B.js → index-Cn8vvE6a.js} +1 -1
  65. package/dist/storybook/assets/{onFind-CqIRRMTv.js → onFind-DJOHkvQ2.js} +1 -1
  66. package/dist/storybook/assets/{onFind.stories-C4PPQTaQ.js → onFind.stories-CTmXCV_g.js} +1 -1
  67. package/dist/storybook/assets/{onRemove.stories-BGFCh6DN.js → onRemove.stories-r7-2gQn3.js} +1 -1
  68. package/dist/storybook/assets/{onVisible.stories-4ni7syfJ.js → onVisible.stories-B_Lx-0SL.js} +1 -1
  69. package/dist/storybook/assets/{style-map-BhvFBtuB.js → style-map-uSz4USKK.js} +1 -1
  70. package/dist/storybook/assets/{syntaxhighlighter-ED5Y7EFY-D_cJwnoJ.js → syntaxhighlighter-ED5Y7EFY-D36nxrU2.js} +1 -1
  71. package/dist/storybook/iframe.html +2 -2
  72. package/dist/storybook/index.json +1 -1
  73. package/dist/storybook/project.json +1 -1
  74. package/dist/tailwind-plugin-badge.js +2 -2
  75. package/dist/tailwind-plugin-badge.ts +3 -3
  76. package/dist/tailwind-plugin-button-group.js +50 -27
  77. package/dist/tailwind-plugin-button-group.js.map +1 -1
  78. package/dist/tailwind-plugin-button-group.ts +61 -33
  79. package/dist/tailwind-plugin-button.js +15 -5
  80. package/dist/tailwind-plugin-button.js.map +1 -1
  81. package/dist/tailwind-plugin-button.ts +16 -5
  82. package/dist/tailwind-plugin-pagination.js +4 -1
  83. package/dist/tailwind-plugin-pagination.js.map +1 -1
  84. package/dist/tailwind-plugin-pagination.ts +4 -1
  85. package/dist/tailwind-plugin-popover.js +90 -23
  86. package/dist/tailwind-plugin-popover.js.map +1 -1
  87. package/dist/tailwind-plugin-popover.ts +95 -25
  88. package/dist/tailwind-plugin-tooltip.js +3 -0
  89. package/dist/tailwind-plugin-tooltip.js.map +1 -1
  90. package/dist/tailwind-plugin-tooltip.ts +3 -0
  91. package/docs/components/ActionBar.md +9 -8
  92. package/docs/components/Avatar.md +20 -19
  93. package/docs/components/AvatarGroup.md +5 -4
  94. package/docs/components/Badge.md +8 -7
  95. package/docs/components/ButtonGroup.md +12 -11
  96. package/docs/components/Icon.md +8 -7
  97. package/docs/components/Pagination.md +19 -18
  98. package/docs/components/Popover.md +21 -17
  99. package/docs/components/Tab.md +13 -12
  100. package/docs/components/Tabs.md +13 -12
  101. package/package.json +1 -1
  102. package/src/legacy/tool-ui/src/Admin.css +10 -1
  103. package/src/legacy/tool-ui/src/CodeMirror.css +4 -3
  104. package/src/legacy/tool-ui/src/ContentInputGroup.css +86 -62
  105. package/src/legacy/tool-ui/src/ContentInputGroup.ts +33 -0
  106. package/src/legacy/tool-ui/src/Conversation.ts +3 -0
  107. package/src/legacy/tool-ui/src/Entry.ts +1 -0
  108. package/src/legacy/tool-ui/src/Global.d.ts +3 -0
  109. package/src/legacy/tool-ui/src/LocationMap.css +106 -2
  110. package/src/legacy/tool-ui/src/MenuView.css +1 -2
  111. package/src/legacy/tool-ui/src/NewTabLinks.ts +25 -0
  112. package/src/legacy/tool-ui/src/Notification.css +20 -2
  113. package/src/legacy/tool-ui/src/Notifications.ts +5 -0
  114. package/src/legacy/tool-ui/src/RepeatableContentInputGroup.css +28 -21
  115. package/src/legacy/tool-ui/src/RepeatableContentSelector.css +50 -50
  116. package/src/legacy/tool-ui/src/SearchResult.css +5 -0
  117. package/src/legacy/tool-ui/src/Suggestions.css +1 -1
  118. package/src/legacy/tool-ui/src/form/CodeInput/CodeMirror.ts +0 -1
  119. package/src/legacy/tool-ui/src/main/webapp/dist/130.8cc1870de35c48fb16bc.js +1 -0
  120. package/src/legacy/tool-ui/src/main/webapp/dist/CodeMirror.deeefe0da1691332b8d9.js +1 -0
  121. package/src/legacy/tool-ui/src/main/webapp/dist/{RTEProseMirror.420477026fe7508c83cf.js → RTEProseMirror.3ab7e02ee7ea42af94e5.js} +6 -6
  122. package/src/legacy/tool-ui/src/main/webapp/dist/iframeResizer.contentWindow.min.ea954ff5c2278da22eb4.js +2 -0
  123. package/src/legacy/tool-ui/src/main/webapp/dist/iframeResizer.contentWindow.min.ea954ff5c2278da22eb4.js.LICENSE.txt +7 -0
  124. package/src/legacy/tool-ui/src/main/webapp/dist/lucide.a0ab0ebd23916ff7c28c.woff2 +0 -0
  125. package/src/legacy/tool-ui/src/main/webapp/dist/{v4.f3d988f6f7e664a8ac1f.js → v4.77773a9500063c0e2e37.js} +6 -6
  126. package/src/legacy/tool-ui/src/main/webapp/dist/v4.d48271241dbf3eecc14e.css +3 -0
  127. package/src/legacy/tool-ui/src/main/webapp/dist/v5.78c144a01e1cf543642b.css +5 -0
  128. package/src/legacy/tool-ui/src/main/webapp/dist/{v5.9aca525c9803b3173f73.js → v5.9f309b0ce98df4565933.js} +6 -6
  129. package/src/legacy/tool-ui/src/main/webapp/v4/ContentEdit.less +1 -0
  130. package/src/legacy/tool-ui/src/main/webapp/v4/Entry.less +7 -0
  131. package/src/legacy/tool-ui/src/main/webapp/v4/SearchResult.less +7 -0
  132. package/src/legacy/tool-ui/src/v5.css +9 -0
  133. package/src/legacy/tool-ui/src/v5.ts +13 -0
  134. package/dist/storybook/assets/if-defined-Dl8MuiCE.js +0 -1
  135. package/dist/storybook/assets/iframe-HDp5BmO_.css +0 -1
  136. package/src/legacy/tool-ui/src/main/webapp/dist/2825.c1342ac2662d11fd4125.js +0 -1
  137. package/src/legacy/tool-ui/src/main/webapp/dist/CodeMirror.5ddffe054374f883d6f8.js +0 -1
  138. package/src/legacy/tool-ui/src/main/webapp/dist/v4.05d6a78ae435b930dd53.css +0 -3
  139. package/src/legacy/tool-ui/src/main/webapp/dist/v5.95b7459d6c50c61b6480.css +0 -5
  140. /package/src/legacy/tool-ui/src/main/webapp/dist/{RTEProseMirror.420477026fe7508c83cf.js.LICENSE.txt → RTEProseMirror.3ab7e02ee7ea42af94e5.js.LICENSE.txt} +0 -0
  141. /package/src/legacy/tool-ui/src/main/webapp/dist/{v4.f3d988f6f7e664a8ac1f.js.LICENSE.txt → v4.77773a9500063c0e2e37.js.LICENSE.txt} +0 -0
  142. /package/src/legacy/tool-ui/src/main/webapp/dist/{v5.9aca525c9803b3173f73.js.LICENSE.txt → v5.9f309b0ce98df4565933.js.LICENSE.txt} +0 -0
@@ -29,34 +29,24 @@
29
29
 
30
30
  .CIG-label {
31
31
  /* line-height is set here to make sure that labels with/without action icons are always the same height */
32
- @apply relative -order-2 flex h-min items-center text-sm font-semibold leading-6 text-gray-700;
32
+ @apply relative -order-2 flex h-min items-center gap-x-1 text-sm font-semibold leading-6 text-gray-700;
33
33
  }
34
34
 
35
35
  .CIG-label label {
36
36
  @apply min-w-max;
37
37
  }
38
38
 
39
- .CIG-requiredLabel {
40
- @apply ps-2 text-sm font-normal text-gray-500;
39
+ /* Hide the redundant text label on unlabeled fields; child-scoped so nested fields' labels survive. */
40
+ .CIG-row.is-unlabeled > .CIG-label label {
41
+ @apply hidden;
41
42
  }
42
43
 
43
- /* Adjusts spacing between RCIG-list, view switcher and label when "Items Type" dropdown is missing */
44
- .CIG-label + .CIG-large .RCIG.is-previewable > {
45
- .repeatablePreviewControls {
46
- @apply top-[calc(theme(fontSize.md.1)_-_theme(spacing.7))];
47
- }
48
-
49
- .RCIG-expandAll {
50
- @apply top-[calc(0px_-_theme(spacing.2)_*_2_-_theme(iconSize.lg)_+_theme(fontSize.md.1))];
51
- }
52
-
53
- .repeatablePreviewControls + .RCIG-list {
54
- @apply mt-[calc(theme(fontSize.md.1)_+_theme(spacing.2))];
55
- }
44
+ .CIG-requiredLabel {
45
+ @apply text-sm font-normal text-gray-500;
56
46
  }
57
47
 
58
48
  .CIG-comments {
59
- @apply ms-1 delay-[0.12s] before:btu-icon-message-circle-plus;
49
+ @apply delay-[0.12s] before:btu-icon-message-circle-plus;
60
50
 
61
51
  &.has-comments {
62
52
  @apply before:btu-icon-message-circle after:absolute after:right-[2px] after:top-[4px] after:size-[10px] after:rounded-full after:border after:bg-error-600 after:[clip-path:circle()] hover:bg-primary-50 hover:text-primary-800;
@@ -64,11 +54,11 @@
64
54
  }
65
55
 
66
56
  .CIG-help {
67
- @apply ms-1 before:btu-icon-wrench;
57
+ @apply before:btu-icon-wrench;
68
58
  }
69
59
 
70
60
  .CIG-guide {
71
- @apply ms-2 before:btu-icon-circle-help;
61
+ @apply before:btu-icon-circle-help;
72
62
  }
73
63
 
74
64
  .CIG-guide,
@@ -78,15 +68,12 @@
78
68
  }
79
69
 
80
70
  .CIG-wordCount {
81
- --space: 0.375rem;
82
- @apply order-last ms-auto mt-[--space] text-sm font-normal text-gray-500 opacity-0;
71
+ --space: 0.25rem;
72
+ /* ms-auto right-aligns the count; with a note present its flex-grow eats the free space first, so this only bites when there's no note. */
73
+ @apply order-last ms-auto flex flex-none justify-end gap-1 whitespace-nowrap text-sm font-normal text-gray-500 opacity-0;
83
74
 
84
75
  &.has-min-or-max {
85
- @apply flex justify-end opacity-100;
86
-
87
- .CIG-wordCount-min + .CIG-wordCount-max {
88
- @apply ps-1;
89
- }
76
+ @apply opacity-100;
90
77
  }
91
78
  }
92
79
 
@@ -126,12 +113,9 @@
126
113
  @apply relative order-[-1] -mx-[--space] w-screen;
127
114
  }
128
115
 
129
- .CIG > .CIG-note > .CIG-noteItem {
130
- @apply mt-0;
131
- }
132
-
116
+ /* Embedded note: flush divider, not the rounded row-note card. */
133
117
  .CIG > .CIG-note > .CIG-noteItem > .Message {
134
- @apply my-0 rounded-none border-0 border-b;
118
+ @apply rounded-none border-0 border-b;
135
119
  }
136
120
 
137
121
  .CIG-note:empty,
@@ -139,21 +123,35 @@
139
123
  @apply hidden;
140
124
  }
141
125
 
142
- .CIG-row > .CIG-note,
126
+ .CIG-row > .CIG-note {
127
+ @apply order-12 w-full min-w-0 flex-1 text-sm text-gray-500;
128
+ }
129
+
143
130
  .CIG-noteItem {
144
- @apply order-12 mt-1.5 w-full basis-full text-sm text-gray-500;
145
- [data-dynamic-html] .Message {
146
- @apply mb-0 mt-1.5 [overflow-wrap:anywhere];
147
- }
131
+ @apply text-sm text-gray-500;
132
+ }
133
+
134
+ /* Outranks .Widget .Message:not(:has(+*)) to drop its margins; keeps its rounded border. */
135
+ .CIG-note > .CIG-noteItem > .Message {
136
+ @apply my-0 [overflow-wrap:anywhere];
148
137
  }
149
138
 
150
139
  /* Fields marked with @NotePosition(ABOVE) (defaulted for embedded/clustered fields) */
151
140
  .CIG-row > .CIG-note.is-note-above {
152
- @apply order-[-1] mb-1.5 mt-0 w-full basis-full;
141
+ @apply order-[-1] me-0 w-full basis-full;
142
+ }
143
+
144
+ /* A list's note sits above the list, full-width (not shrunk beside it by its flex-1 base).
145
+ .has-RCS is stamped on the row by ContentInputGroup.ts in place of :has(> .CIG-small.RCS). */
146
+ .CIG-row.has-RCS > .CIG-note {
147
+ @apply order-[-1] basis-full;
153
148
  }
154
149
 
155
- .CIG-row > .CIG-note.is-note-above > .CIG-noteItem {
156
- @apply mt-0;
150
+ /* Shrink note-above width when the expandAll button is visible so they sit side by side.
151
+ .has-expandAll is stamped on the row by RepeatableContentInputGroup.js in place of
152
+ :has(.RCIG-expandAll). */
153
+ .CIG-row.is-expandable.has-expandAll > .CIG-note.is-note-above {
154
+ @apply max-w-[calc(100%-theme(spacing.7)-theme(spacing.2))];
157
155
  }
158
156
 
159
157
  /* Equalize the ComboInput widths so that they look aligned. */
@@ -171,7 +169,13 @@
171
169
  @apply w-full;
172
170
  }
173
171
 
174
- /* Inside a layout with columns, unset the min width to prevent fields from
172
+ /* min() replaces a @[312px]/CIG gate. Pixel-identical only while .CIG-row keeps
173
+ contain:inline-size - otherwise the 100% inflates intrinsic widths. */
174
+ > .CIG-small.inputSmall:not(.is-grid) {
175
+ @apply min-w-[min(312px,100%)] max-w-[540px] basis-1/2;
176
+ }
177
+
178
+ /* Inside a layout with columns, unset the min width to prevent fields from
175
179
  overlapping on smaller viewports. Set flex basis back to full so that the fields are not
176
180
  really small here. These will still get the max width of 540px. */
177
181
  &.is-minimal,
@@ -191,7 +195,7 @@
191
195
  .CIG-large,
192
196
  .CIG-small {
193
197
  --CIG-space: 0.375rem;
194
- @apply mt-[--CIG-space] basis-full;
198
+ @apply basis-full;
195
199
  }
196
200
 
197
201
  .CIG > .TemplateField {
@@ -207,7 +211,7 @@
207
211
  /* contain:inline-size, NOT @container. The containment is load-bearing: it stops
208
212
  descendant min-content widths propagating up, else .Admin-main scrolls sideways.
209
213
  The query container is what was slow - 13,158ms/layout vs 44ms for containment alone. */
210
- @apply relative flex max-h-min min-w-[200px] basis-full flex-row flex-wrap content-start [contain:inline-size];
214
+ @apply relative flex max-h-min min-w-[200px] basis-full flex-row flex-wrap content-start gap-1 [contain:inline-size];
211
215
 
212
216
  /* The colored vertical "thread" to the side of each row.
213
217
  The 1px left offset is to stay true to the design so that there is a slight gap betweem the thread and container.
@@ -216,19 +220,24 @@
216
220
  @apply absolute bottom-0 left-[calc(1px_-_var(--space))] top-[3px] w-0.5 origin-left scale-x-0 rounded-lg bg-primary-600 opacity-0 transition;
217
221
  }
218
222
 
223
+ /* Stop the thread above the word count (which adds height when it isn't pulled up).
224
+ .has-wordCount is stamped on the row by v3.js updateWordCount() in place of
225
+ :has(> .CIG-wordCount), which onFind blacklists. */
226
+ &.has-wordCount::after {
227
+ @apply bottom-[calc(0.25rem_+_theme(lineHeight.4))]; /* clears the word count: row gap (gap-1) + its line height */
228
+ }
229
+
219
230
  /* Rows could be empty or have no visible children. */
220
231
  &:empty,
221
232
  &:has(> [type='hidden']:only-child) {
222
233
  @apply hidden;
223
234
  }
224
235
 
225
- /* Show word count when focused */
226
- &:focus-within {
227
- .CIG-wordCount {
228
- @apply opacity-100;
236
+ /* Child combinator: focusing a nested field must not reveal ancestor rows' word counts. */
237
+ &:focus-within > .CIG-wordCount {
238
+ @apply opacity-100;
229
239
 
230
- transition: opacity 0.25s cubic-bezier(0.25, 0, 0.2, 1);
231
- }
240
+ transition: opacity 0.25s cubic-bezier(0.25, 0, 0.2, 1);
232
241
  }
233
242
 
234
243
  /* hidden/unselected Tab Container CIG-rows, shouldn't have padding */
@@ -236,9 +245,21 @@
236
245
  @apply mt-[--CIG-row-space];
237
246
  }
238
247
 
239
- /* Word count element in all Cig rows (except the last sibling row). */
240
- &:has(+ .CIG-row) .CIG-wordCount {
241
- @apply mb-[calc(-1_*_(var(--space)_+_theme(lineHeight.4)))]; /* negative margin keeps the word count from pushing the next CIG-row down. */
248
+ /* Extra top clearance so the pulled-up expand-all button clears the preceding field's word count. */
249
+ &.inputContainer.is-expandable {
250
+ @apply mt-[calc(var(--CIG-row-space)_+_0.25rem)];
251
+ }
252
+
253
+ /* A following sibling means the word count is pulled up, so the thread runs full-height.
254
+ .has-nextRow is stamped by ContentInputGroup.ts in place of :has(+ .CIG-row). */
255
+ &.has-nextRow {
256
+ &.has-wordCount::after {
257
+ @apply bottom-0;
258
+ }
259
+
260
+ > .CIG-wordCount {
261
+ @apply mb-[calc(-1_*_(var(--space)_+_theme(lineHeight.4)))]; /* negative margin keeps the word count from pushing the next CIG-row down. */
262
+ }
242
263
  }
243
264
  }
244
265
 
@@ -249,10 +270,9 @@
249
270
  @apply w-full basis-full;
250
271
  }
251
272
 
252
- /*
253
- Fades out the surrounding buttons when the user focuses the input. */
273
+ /* Match the row directly: :has(.is-highlighted) would also fade ancestor rows' buttons. */
254
274
  .CIG-row.is-inputFocused,
255
- .CIG-row:has(.is-highlighted) {
275
+ .CIG-row.is-highlighted {
256
276
  > .CIG-label .CIG-guide:not(:hover),
257
277
  > .CIG-label .CIG-help:not(:hover),
258
278
  > .CIG-label .CIG-comments:not(:hover),
@@ -377,6 +397,15 @@
377
397
  @apply focus:ring-error-100 focus:border-error-600;
378
398
  }
379
399
  }
400
+
401
+ /* Don't bleed the error focus ring into a nested embedded field's inputs, unless
402
+ that nested row is itself in error (is-error propagates up every ancestor row). */
403
+ .CIG-row:not(.is-error) {
404
+ input,
405
+ textarea {
406
+ @apply focus:ring-primary-100 focus:border-primary-600;
407
+ }
408
+ }
380
409
  }
381
410
 
382
411
  /* Gray/yellow thread when the row is pending change. */
@@ -419,7 +448,7 @@
419
448
  @apply pt-0;
420
449
  }
421
450
 
422
- /* Remove all gaps around CIG inside unlabeled row by itself. */
451
+ /* Collapse a lone unlabeled embedded record's box. Excludes RCIG bodies: tabless modules would match here (direct-child rows), tabbed wouldn't. */
423
452
  .CIG-row:where(
424
453
  [data-type='record'],
425
454
  [data-type='list/record'],
@@ -427,8 +456,7 @@
427
456
  )
428
457
  > .CIG-large {
429
458
  > .toggleable-form > .CIG,
430
- > .CIG,
431
- > .RCIG-list > .RCIG-item > .CIG {
459
+ > .CIG {
432
460
  &:has(> div.CIG-row.is-unlabeled:where(:only-of-type, :last-child)) {
433
461
  @apply rounded-none border-none p-0;
434
462
  }
@@ -578,10 +606,6 @@
578
606
  }
579
607
  }
580
608
 
581
- .CIG-row:only-child.is-unlabeled > .Message.is-error {
582
- @apply ms-[calc(var(--CIG-padding)_+_theme(spacing.4))];
583
- }
584
-
585
609
  /* Query Field support. */
586
610
  .CIG.TC.is-query {
587
611
  --CIG-padding: 0;
@@ -655,7 +679,7 @@
655
679
  }
656
680
 
657
681
  .CIG-small > .DateStringCalendarEmbedded .DateStringCalendarEmbedded-widget {
658
- @apply blokk border-none;
682
+ @apply border-none blokk;
659
683
 
660
684
  .DateStringCalendarTime,
661
685
  /* Unset the horizontal borders which appear in these pseudo-elements */
@@ -12,13 +12,46 @@ const toggleEmpty = (group: Element) => {
12
12
  group.classList.toggle('is-empty', !rows.length)
13
13
  }
14
14
 
15
+ // Flag a row immediately followed by another row so CSS can pull up its word count
16
+ // with a plain class instead of :has(+ .CIG-row).
17
+ const updateHasNextRow = (row: Element) => {
18
+ row.classList.toggle(
19
+ 'has-nextRow',
20
+ row.nextElementSibling?.matches('.CIG-row') ?? false,
21
+ )
22
+ }
23
+
15
24
  onFind('.CIG', toggleEmpty)
16
25
 
26
+ // Rows stream in asynchronously, so recompute each as it arrives, plus the row before
27
+ // it, whose follower is now this one. A snapshot at group-find time would miss rows
28
+ // inserted later and leave the word count pushing the next field down.
29
+ onFind('.CIG-row', (row) => {
30
+ updateHasNextRow(row)
31
+ const previous = row.previousElementSibling
32
+ if (previous?.matches('.CIG-row')) {
33
+ updateHasNextRow(previous)
34
+ }
35
+ })
36
+
17
37
  window.addEventListener('brightspot-content-state-change', ({ target }) => {
18
38
  if (!(target instanceof HTMLElement)) return
19
39
  for (const group of target.querySelectorAll('.CIG')) {
20
40
  toggleEmpty(group)
21
41
  }
42
+ // Recompute adjacency across the changed subtree to cover removals and reorders.
43
+ for (const row of target.querySelectorAll('.CIG-row')) {
44
+ updateHasNextRow(row)
45
+ }
46
+ })
47
+
48
+ // Flag the row of a compact collection (RCS) control so its note can go full-width
49
+ // above the control with a plain class instead of :has(> .CIG-small.RCS).
50
+ onFind('.CIG-small.RCS', (control) => {
51
+ const row = control.parentElement
52
+ if (row?.classList.contains('CIG-row')) {
53
+ row.classList.add('has-RCS')
54
+ }
22
55
  })
23
56
 
24
57
  // Move CIG-title to be more consistently placed.
@@ -424,6 +424,9 @@ onFind('.frame[name^=conversation-edit-post].loaded', (widget: HTMLElement) => {
424
424
 
425
425
  onFind('.Conversation-add-comment', (button) => {
426
426
  button.addEventListener('click', (event) => {
427
+ // This has no href, so keep the frame plugin from treating it as a link.
428
+ event.stopPropagation()
429
+
427
430
  const workflowBody = button.closest('.ContentEdit-workflowBody')
428
431
  if (workflowBody) {
429
432
  workflowBody
@@ -16,6 +16,7 @@ import './Diff'
16
16
  import './ExternalCalendars'
17
17
  import './ExternalItemObjects'
18
18
  import './LiveBlog'
19
+ import './NewTabLinks'
19
20
  import './Notifications'
20
21
  import './PostPublish'
21
22
  import './PrePublish'
@@ -3,6 +3,9 @@ export {}
3
3
  declare global {
4
4
  interface Window {
5
5
  BRIGHTSPOT: {
6
+ a11y?: {
7
+ opensInNewWindow?: string
8
+ }
6
9
  ai: {
7
10
  AI_CHAT_ENABLED: boolean
8
11
  submitSuggestion: string
@@ -1,6 +1,110 @@
1
1
  .locationMap,
2
2
  .regionMap {
3
- @apply z-0 h-[50dvh];
3
+ @apply z-0 h-[50dvh] !bg-gray-100;
4
+
5
+ /* Leaflet's chrome ships as unlayered CSS (JS imports), so overrides need `!`
6
+ to outrank it. */
7
+
8
+ /* OSM tiles are light-only; invert only the tile pane so other panes (markers,
9
+ regions, controls, popups) keep their true colors. */
10
+ .leaflet-tile-pane {
11
+ @apply dark:[filter:invert(1)_hue-rotate(180deg)_brightness(0.95)_contrast(0.9)];
12
+ }
13
+
14
+ .leaflet-bar a {
15
+ @apply !border-gray-200 !bg-white !text-gray-700 hover:!bg-gray-100;
16
+
17
+ &.leaflet-disabled {
18
+ @apply !text-gray-400;
19
+ }
20
+ }
21
+
22
+ .leaflet-control-attribution {
23
+ @apply !bg-white !text-gray-600;
24
+
25
+ a {
26
+ @apply !text-primary-600;
27
+ }
28
+ }
29
+
30
+ .leaflet-popup-content-wrapper,
31
+ .leaflet-popup-tip {
32
+ @apply !bg-white !text-gray-700;
33
+ }
34
+
35
+ .leaflet-popup-close-button {
36
+ @apply !text-gray-500 hover:!text-gray-700;
37
+ }
38
+
39
+ .leaflet-tooltip {
40
+ @apply !border-gray-200 !bg-white !text-gray-700;
41
+ }
42
+ /* Arrow color must track the tooltip surface */
43
+ .leaflet-tooltip-top::before {
44
+ @apply !border-t-white;
45
+ }
46
+ .leaflet-tooltip-bottom::before {
47
+ @apply !border-b-white;
48
+ }
49
+ .leaflet-tooltip-left::before {
50
+ @apply !border-l-white;
51
+ }
52
+ .leaflet-tooltip-right::before {
53
+ @apply !border-r-white;
54
+ }
55
+
56
+ .leaflet-control-geosearch form,
57
+ .leaflet-control-geosearch form input {
58
+ @apply !bg-white !text-gray-700;
59
+ }
60
+ .leaflet-control-geosearch a.leaflet-bar-part::before {
61
+ @apply !border-t-gray-600;
62
+ }
63
+ .leaflet-control-geosearch a.leaflet-bar-part::after {
64
+ @apply !border-gray-600;
65
+ }
66
+ .leaflet-control-geosearch .results {
67
+ @apply !bg-white !text-gray-700;
68
+ }
69
+ .leaflet-control-geosearch .results.active {
70
+ @apply !border-t-gray-200;
71
+ }
72
+ .leaflet-control-geosearch .results > .active,
73
+ .leaflet-control-geosearch .results > :hover {
74
+ @apply !border-gray-200 !bg-gray-100;
75
+ }
76
+ /* Transparent so it doesn't paint over the input's focus ring */
77
+ .leaflet-control-geosearch button.reset {
78
+ @apply !bg-transparent !px-4 !text-gray-500 hover:!text-gray-700;
79
+ }
80
+
81
+ /* Leaflet-draw's sprite glyphs don't theme and fail to invert cleanly; swap
82
+ them for design-system icons, like the locate/remove controls do. */
83
+ .leaflet-draw-toolbar a {
84
+ @apply flex items-center justify-center !bg-none before:btu-icon;
85
+ }
86
+ .leaflet-draw-draw-polygon {
87
+ @apply before:btu-icon-pentagon;
88
+ }
89
+ .leaflet-draw-draw-circle {
90
+ @apply before:btu-icon-circle;
91
+ }
92
+ .leaflet-draw-edit-edit {
93
+ @apply before:btu-icon-square-pen;
94
+ }
95
+ .leaflet-draw-edit-remove {
96
+ @apply before:btu-icon-trash-2;
97
+ }
98
+
99
+ /* Finish / Delete / Cancel action buttons */
100
+ .leaflet-draw-actions a {
101
+ @apply !border-gray-200 !bg-white !text-gray-700 hover:!bg-gray-100;
102
+ }
103
+
104
+ /* Overrides Leaflet's SVG stroke/fill presentation attributes */
105
+ .leaflet-overlay-pane path {
106
+ @apply !fill-primary-500 !stroke-primary-700;
107
+ }
4
108
  }
5
109
 
6
110
  .LocationMap-removeMarker {
@@ -13,7 +117,7 @@
13
117
 
14
118
  .LocationMap-marker {
15
119
  --size: 20px;
16
- @apply !size-[var(--size)] before:blokk before:size-full before:bg-gradient-to-tr before:from-primary-500 before:via-primary-700 before:to-primary-900 before:[clip-path:theme(shape.mapPin)];
120
+ @apply !size-[var(--size)] before:size-full before:bg-gradient-to-tr before:from-primary-500 before:via-primary-700 before:to-primary-900 before:blokk before:[clip-path:theme(shape.mapPin)];
17
121
  }
18
122
 
19
123
  .LocationMap-locateControl {
@@ -124,8 +124,7 @@
124
124
  }
125
125
 
126
126
  .CIG-wordCount {
127
- /* pointer-events-none keeps the status box from swallowing clicks meant for the overflow button beneath it */
128
- @apply pointer-events-none absolute end-3 top-1.5 z-10 opacity-100;
127
+ @apply pointer-events-none absolute end-3 top-3 z-10 opacity-100;
129
128
 
130
129
  /* Override inline styles from JS */
131
130
  @apply [--ProseMirror-wordCountSpacingWithOneIcon:52px] [--ProseMirror-wordCountSpacingWithThreeIcons:120px] [--ProseMirror-wordCountSpacingWithTwoIcons:85px];
@@ -0,0 +1,25 @@
1
+ import onFind from './dom/onFind'
2
+
3
+ // Announces "opens in a new window" to screen readers. On the frontend so it also covers
4
+ // plugin/message/dialog links; the onFind blacklist skips editorial content.
5
+ onFind('a[target="_blank"]:not([download])', (link: HTMLAnchorElement) => {
6
+ const notice = window.BRIGHTSPOT?.a11y?.opensInNewWindow
7
+ if (!notice) {
8
+ return
9
+ }
10
+
11
+ // Match the accessible-name order (aria-label > text > title) so we compose, not clobber, an
12
+ // existing name. We set aria-label, not a child span: a span leaks into textContent, which
13
+ // other code reads for titles.
14
+ const name =
15
+ link.getAttribute('aria-label')?.trim() ||
16
+ link.textContent?.trim() ||
17
+ link.getAttribute('title')?.trim() ||
18
+ ''
19
+ if (!name) {
20
+ // Icon-only link with no accessible name — announce the notice on its own.
21
+ link.setAttribute('aria-label', notice)
22
+ } else if (!name.includes(notice)) {
23
+ link.setAttribute('aria-label', `${name}, ${notice}`)
24
+ }
25
+ })
@@ -33,7 +33,7 @@
33
33
  }
34
34
 
35
35
  .Notification-clear {
36
- @apply order-1 ms-auto;
36
+ @apply order-1 ms-auto shrink-0;
37
37
 
38
38
  .Button-clearSingle {
39
39
  @apply btu-button btu-button-text-hidden btu-button-fill-none btu-button-error opacity-0 before:btu-icon before:btu-icon-x;
@@ -133,12 +133,30 @@
133
133
  @apply Dropdown-item;
134
134
  }
135
135
 
136
+ /* The topic label is the only element that says what the notification is, so it leads
137
+ the row. It previously inherited .Notification-info's 12px/400 while the action sat
138
+ beside it as a filled primary button, which read as an offer to unsubscribe with the
139
+ notification as its caption.
140
+
141
+ Declared through custom properties rather than utilities because the markup is emitted
142
+ from Java with fixed class names: without a seam, a consumer retuning this row has to
143
+ redeclare these platform classes with hardcoded values. */
136
144
  .Notification-type {
137
145
  @apply truncate;
146
+
147
+ font-size: var(--notification-topic-font-size, 0.875rem);
148
+ font-weight: var(--notification-topic-font-weight, 600);
149
+ /* Worth several characters of fit at weight 600, on a label that ellipses. */
150
+ letter-spacing: var(--notification-topic-letter-spacing, -0.01em);
151
+ line-height: var(--notification-topic-line-height, 1.25rem);
138
152
  }
139
153
 
154
+ /* The label absorbs shrink pressure by ellipsis; the timestamp has no such escape and
155
+ would otherwise break at its space and be clipped by the title's overflow. */
140
156
  .Notification-time {
141
- @apply flex before:size-[1.125rem] before:bg-gray-500 before:[clip-path:circle(0.1rem)];
157
+ @apply flex whitespace-nowrap before:size-[1.125rem] before:bg-gray-500 before:[clip-path:circle(0.1rem)];
158
+
159
+ font-size: var(--notification-time-font-size, inherit);
142
160
  }
143
161
 
144
162
  .Notification-details {
@@ -89,6 +89,11 @@ onFind(
89
89
  },
90
90
  )
91
91
 
92
+ // Move focus to the result link when the popup opens so keyboard and screen reader users can act on it.
93
+ onFind('.Notification-actionResultUrl-link[data-autofocus]', (link: HTMLElement) => {
94
+ link.focus()
95
+ })
96
+
92
97
  onFind('.Notification-actionBar', (actionBar: HTMLElement) => {
93
98
  const limit: string | null = actionBar.getAttribute('actionLimit')
94
99
  const list: HTMLElement = create('ul', {
@@ -78,15 +78,16 @@
78
78
  .RCIG.is-addToTop {
79
79
  @apply grid grid-cols-[1fr_auto] grid-rows-[auto_1fr] gap-2;
80
80
 
81
- .RCIG-expandAll {
81
+ /* Direct children: grid placement must not reach a nested RCIG's controls. */
82
+ > .RCIG-expandAll {
82
83
  @apply static col-start-2 self-center;
83
84
  }
84
85
 
85
- .RCIG-controls {
86
+ > .RCIG-controls {
86
87
  @apply col-start-1 row-start-1;
87
88
  }
88
89
 
89
- .RCIG-list:not(:empty) {
90
+ > .RCIG-list:not(:empty) {
90
91
  @apply col-span-full mb-0;
91
92
  }
92
93
  }
@@ -211,35 +212,34 @@
211
212
 
212
213
  .RCIG-expandAll {
213
214
  --border-size: 1px;
214
- @apply btu-button btu-button-text-hidden btu-button-outline btu-button-fill-none btu-button-gray btu-button-sm absolute right-[--border-size] top-[calc(-1_*_(var(--button-size-sm)_+_var(--CIG-space,0))_-_var(--border-size))] before:btu-icon before:btu-icon-chevrons-up-down;
215
+ @apply btu-button btu-button-text-hidden btu-button-outline btu-button-fill-none btu-button-gray btu-button-xs absolute right-[--border-size] top-[calc(-1_*_(var(--button-size-xs)_+_var(--CIG-space,0))_-_var(--border-size))] before:btu-icon before:btu-icon-chevrons-up-down;
215
216
 
216
217
  &.is-expanded {
217
218
  @apply before:btu-icon-chevrons-down-up;
218
219
  }
219
220
  }
220
221
 
222
+ /* sm to match the view-switcher's height when it shares the row. */
223
+ .RCIG.is-previewable > .RCIG-expandAll {
224
+ @apply btu-button-sm top-[calc(-1_*_(var(--button-size-sm)_+_var(--CIG-space,0))_-_var(--border-size))];
225
+ }
226
+
221
227
  .RCIG[data-rcig-size='0'] {
222
- .RCIG-expandAll,
223
- .RCIG-resetWeights {
228
+ > .RCIG-expandAll,
229
+ > .RCIG-resetWeights {
224
230
  @apply hidden;
225
231
  }
226
-
227
- &.is-previewable .repeatablePreviewControls {
228
- @apply right-0;
229
- }
230
232
  }
231
233
 
232
234
  .RCIG.is-previewable {
233
235
  > .repeatablePreviewControls {
234
- @apply absolute right-11 top-[calc(-1_*_(38px_+_var(--CIG-space,0)))];
235
- }
236
-
237
- &.is-gridView > .repeatablePreviewControls {
238
- @apply right-0;
236
+ @apply absolute right-0 top-[calc(-1_*_(38px_+_var(--CIG-space,0)))];
239
237
  }
240
238
 
241
- &.is-gridView > .RCIG-expandAll {
242
- @apply hidden;
239
+ /* .has-expandAll is stamped on this RCIG by RepeatableContentInputGroup.js in place of
240
+ :has(> .RCIG-expandAll); excludes emptied lists (button present but hidden). */
241
+ &.has-expandAll:not([data-rcig-size='0']) > .repeatablePreviewControls {
242
+ @apply right-11;
243
243
  }
244
244
  }
245
245
 
@@ -362,7 +362,7 @@
362
362
  }
363
363
 
364
364
  .ContentSelector-search {
365
- @apply row-start-1 before:absolute before:end-[calc(theme(size.9)*2_+_theme(spacing.1))] before:top-[calc(144px_+_theme(spacing.1))];
365
+ @apply row-start-1 before:top-[calc(144px_+_theme(spacing.1))];
366
366
  }
367
367
 
368
368
  .ContentSelector-search figure {
@@ -415,14 +415,21 @@
415
415
  @apply before:me-[calc(theme(spacing.2)*2+55px)];
416
416
  }
417
417
 
418
- .RCIG-expandAll,
419
- .RCIG-resetWeights {
418
+ > .RCIG-expandAll,
419
+ > .RCIG-resetWeights {
420
420
  @apply btu-button-xs top-[calc(0px-var(--RCIG-buttonSize)-theme(spacing.1))];
421
421
  }
422
422
  }
423
423
 
424
424
  .RCIG-resetWeights {
425
- @apply btu-button btu-button-text-hidden btu-button-outline btu-button-fill-none btu-button-gray absolute right-[calc(var(--RCIG-buttonSize)+theme(spacing.2))] before:btu-icon before:btu-icon-columns-3;
425
+ --border-size: 1px;
426
+ @apply btu-button btu-button-text-hidden btu-button-outline btu-button-fill-none btu-button-gray absolute right-[--border-size] before:btu-icon before:btu-icon-columns-3;
427
+ }
428
+
429
+ /* Offset left to make room for the expand-all button only when it's actually present.
430
+ .has-expandAll is stamped by RepeatableContentInputGroup.js in place of :has(> .RCIG-expandAll). */
431
+ .RCIG.has-expandAll > .RCIG-resetWeights {
432
+ @apply right-[calc(var(--RCIG-buttonSize)+theme(spacing.2))];
426
433
  }
427
434
 
428
435
  .RCIG-weightBar {