@kubex/zinc 1.1.185 → 2.0.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 (358) hide show
  1. package/.browserslistrc +2 -0
  2. package/.github/workflows/js_build_and_deploy.yaml +54 -1
  3. package/.github/workflows/test.yaml +27 -0
  4. package/dist/chunks/zn.UWJLIXDT.js +1 -0
  5. package/dist/custom-elements.json +10319 -2666
  6. package/dist/vscode.html-custom-data.json +1012 -57
  7. package/dist/web-types.json +2097 -145
  8. package/dist/zn.d.ts +2294 -416
  9. package/dist/zn.min.css +1 -1
  10. package/dist/zn.min.js +2310 -1637
  11. package/docs/_includes/default.njk +4 -1
  12. package/docs/assets/scripts/docs.js +22 -6
  13. package/docs/assets/styles/docs.css +9 -2
  14. package/docs/data/report-table-day-compare.json +380 -0
  15. package/docs/data/report-table.json +314 -0
  16. package/docs/pages/components/avatar-group.md +57 -0
  17. package/docs/pages/components/badge.md +67 -0
  18. package/docs/pages/components/button.md +41 -1
  19. package/docs/pages/components/chat-message.md +16 -0
  20. package/docs/pages/components/checkbox.md +1 -1
  21. package/docs/pages/components/chip.md +25 -13
  22. package/docs/pages/components/color-picker.md +37 -0
  23. package/docs/pages/components/copy-button.md +2 -2
  24. package/docs/pages/components/data-table-filter.md +33 -50
  25. package/docs/pages/components/data-table-search.md +4 -4
  26. package/docs/pages/components/data-table.md +27 -3
  27. package/docs/pages/components/date-range.md +116 -0
  28. package/docs/pages/components/dialog.md +29 -37
  29. package/docs/pages/components/diff-row.md +28 -0
  30. package/docs/pages/components/diff.md +46 -0
  31. package/docs/pages/components/editor.md +55 -0
  32. package/docs/pages/components/icon.md +46 -1
  33. package/docs/pages/components/input.md +30 -11
  34. package/docs/pages/components/item.md +35 -0
  35. package/docs/pages/components/key-value.md +25 -0
  36. package/docs/pages/components/menu.md +74 -7
  37. package/docs/pages/components/nav-item.md +15 -0
  38. package/docs/pages/components/nav-list.md +132 -0
  39. package/docs/pages/components/navbar.md +100 -1
  40. package/docs/pages/components/page.md +242 -74
  41. package/docs/pages/components/priority-list.md +43 -5
  42. package/docs/pages/components/query-builder.md +23 -0
  43. package/docs/pages/components/radio-group.md +33 -1
  44. package/docs/pages/components/radio.md +1 -1
  45. package/docs/pages/components/report-table.md +202 -0
  46. package/docs/pages/components/stat.md +30 -0
  47. package/docs/pages/components/tile.md +11 -0
  48. package/docs/pages/components/tooltip.md +1 -1
  49. package/docs/pages/components/translation-grid.md +86 -0
  50. package/docs/pages/components/vertical-stepper.md +108 -64
  51. package/package.json +2 -1
  52. package/scss/_global-spacing.scss +2 -2
  53. package/scss/_root.scss +11 -171
  54. package/scss/boot.scss +14 -0
  55. package/scss/mixins/_helper-mixins.scss +24 -2
  56. package/scss/mixins/_motion-mixins.scss +126 -0
  57. package/scss/mixins/_spacing-mixins.scss +4 -3
  58. package/scss/mixins/_tab-indicator-mixins.scss +12 -0
  59. package/scss/mixins/_typography-mixins.scss +1 -1
  60. package/scss/mixins/index.scss +14 -0
  61. package/scss/shared/_base.scss +32 -1
  62. package/scss/shared/_button-mixin.scss +7 -5
  63. package/scss/shared/_table.scss +35 -4
  64. package/scss/shared/nav.scss +4 -0
  65. package/scss/shared/shimmer.scss +1 -1
  66. package/scss/table-controls.scss +206 -0
  67. package/scss/themes/_dark.scss +1 -3
  68. package/scss/themes/_index.scss +1 -1
  69. package/scss/themes/_light.scss +46 -6
  70. package/scss/themes/_modes.scss +11 -11
  71. package/scss/themes/_openbyte.scss +944 -0
  72. package/scss/themes/_typography.scss +4 -2
  73. package/scss/variables/index.scss +0 -9
  74. package/src/components/alert/alert.component.ts +14 -4
  75. package/src/components/alert/alert.scss +55 -69
  76. package/src/components/alert/alert.test.ts +8 -0
  77. package/src/components/animated-button/animated-button.component.ts +3 -2
  78. package/src/components/animated-button/animated-button.scss +6 -23
  79. package/src/components/animated-button/animated-button.test.ts +4 -3
  80. package/src/components/avatar-group/avatar-group.component.ts +84 -0
  81. package/src/components/avatar-group/avatar-group.scss +54 -0
  82. package/src/components/avatar-group/avatar-group.test.ts +59 -0
  83. package/src/components/avatar-group/index.ts +12 -0
  84. package/src/components/badge/badge.component.ts +49 -0
  85. package/src/components/badge/badge.scss +80 -0
  86. package/src/components/badge/badge.test.ts +34 -0
  87. package/src/components/badge/index.ts +12 -0
  88. package/src/components/bulk-actions/bulk-actions.component.ts +14 -2
  89. package/src/components/button/button.component.ts +228 -8
  90. package/src/components/button/button.scss +115 -32
  91. package/src/components/button/button.test.ts +122 -0
  92. package/src/components/button-menu/button-menu.component.ts +32 -11
  93. package/src/components/button-menu/button-menu.scss +5 -1
  94. package/src/components/channel-tile/channel-tile.component.ts +34 -27
  95. package/src/components/channel-tile/channel-tile.scss +76 -43
  96. package/src/components/chart/builders.test.ts +46 -0
  97. package/src/components/chart/builders.ts +27 -3
  98. package/src/components/chart/chart-live.test.ts +4 -6
  99. package/src/components/chart/chart.component.ts +125 -5
  100. package/src/components/chart/chart.scss +121 -0
  101. package/src/components/chart/chart.test.ts +81 -0
  102. package/src/components/chat-message/chat-message.component.ts +21 -1
  103. package/src/components/chat-message/chat-message.scss +13 -2
  104. package/src/components/chat-message/chat-message.test.ts +9 -0
  105. package/src/components/checkbox/checkbox.component.ts +61 -27
  106. package/src/components/checkbox/checkbox.scss +58 -25
  107. package/src/components/checkbox-group/checkbox-group.component.ts +7 -1
  108. package/src/components/chip/chip.component.ts +11 -1
  109. package/src/components/chip/chip.scss +91 -26
  110. package/src/components/chip/chip.test.ts +17 -0
  111. package/src/components/collapsible/collapsible.component.ts +17 -3
  112. package/src/components/collapsible/collapsible.scss +19 -10
  113. package/src/components/color-picker/color-picker.component.ts +277 -0
  114. package/src/components/color-picker/color-picker.scss +141 -0
  115. package/src/components/color-picker/color-picker.test.ts +57 -0
  116. package/src/components/color-picker/index.ts +12 -0
  117. package/src/components/cols/cols.component.ts +10 -0
  118. package/src/components/cols/cols.test.ts +17 -0
  119. package/src/components/confirm/confirm.component.ts +20 -6
  120. package/src/components/confirm/confirm.test.ts +52 -0
  121. package/src/components/content-block/content-block.component.ts +38 -9
  122. package/src/components/content-block/content-block.scss +11 -5
  123. package/src/components/content-block/content-block.test.ts +26 -0
  124. package/src/components/copy-button/copy-button.component.ts +2 -2
  125. package/src/components/copy-button/copy-button.scss +17 -4
  126. package/src/components/data-select/data-select.component.ts +3 -1
  127. package/src/components/data-table/data-table.component.ts +362 -140
  128. package/src/components/data-table/data-table.scss +136 -60
  129. package/src/components/data-table/data-table.test.ts +356 -4
  130. package/src/components/data-table-filter/data-table-filter.component.ts +426 -406
  131. package/src/components/data-table-filter/data-table-filter.scss +176 -148
  132. package/src/components/data-table-filter/data-table-filter.test.ts +271 -273
  133. package/src/components/data-table-search/data-table-search.component.ts +4 -2
  134. package/src/components/data-table-search/data-table-search.scss +8 -1
  135. package/src/components/data-table-search/data-table-search.test.ts +29 -0
  136. package/src/components/date-range/date-range-math.test.ts +78 -0
  137. package/src/components/date-range/date-range-math.ts +105 -0
  138. package/src/components/date-range/date-range.component.ts +375 -0
  139. package/src/components/date-range/date-range.scss +272 -0
  140. package/src/components/date-range/date-range.test.ts +247 -0
  141. package/src/components/date-range/index.ts +12 -0
  142. package/src/components/datepicker/datepicker.component.ts +44 -7
  143. package/src/components/datepicker/datepicker.scss +9 -0
  144. package/src/components/datepicker/datepicker.test.ts +2 -2
  145. package/src/components/dialog/dialog.component.ts +38 -19
  146. package/src/components/dialog/dialog.scss +65 -36
  147. package/src/components/dialog/dialog.test.ts +14 -0
  148. package/src/components/diff/diff.component.ts +55 -0
  149. package/src/components/diff/diff.scss +46 -0
  150. package/src/components/diff/diff.test.ts +15 -0
  151. package/src/components/diff/index.ts +12 -0
  152. package/src/components/diff-row/diff-row.component.ts +75 -0
  153. package/src/components/diff-row/diff-row.scss +70 -0
  154. package/src/components/diff-row/diff-row.test.ts +37 -0
  155. package/src/components/diff-row/index.ts +12 -0
  156. package/src/components/dropdown/dropdown.component.ts +12 -10
  157. package/src/components/dropdown/dropdown.scss +2 -0
  158. package/src/components/editor/editor.component.ts +159 -11
  159. package/src/components/editor/editor.scss +250 -1
  160. package/src/components/editor/editor.test.ts +31 -3
  161. package/src/components/editor/modules/ai/panel/ai-panel.scss +0 -1
  162. package/src/components/editor/modules/attachment/attachment.ts +53 -31
  163. package/src/components/editor/modules/context-menu/context-menu.ts +17 -0
  164. package/src/components/editor/modules/dialog/dialog.component.ts +23 -1
  165. package/src/components/editor/modules/dialog/dialog.test.ts +28 -0
  166. package/src/components/editor/modules/emoji/emoji.ts +4 -5
  167. package/src/components/editor/modules/merge-field/merge-field.ts +83 -0
  168. package/src/components/editor/modules/toolbar/toolbar.component.ts +121 -68
  169. package/src/components/editor/modules/toolbar/toolbar.scss +38 -0
  170. package/src/components/editor/modules/toolbar/toolbar.ts +25 -1
  171. package/src/components/empty-state/empty-state.component.ts +6 -1
  172. package/src/components/empty-state/empty-state.scss +21 -4
  173. package/src/components/expanding-action/expanding-action.component.ts +22 -34
  174. package/src/components/expanding-action/expanding-action.scss +3 -45
  175. package/src/components/expanding-action/expanding-action.test.ts +2 -1
  176. package/src/components/file/file.component.ts +30 -2
  177. package/src/components/file/file.scss +6 -0
  178. package/src/components/flow-builder/flow-builder.component.ts +36 -3
  179. package/src/components/flow-builder/flow-builder.scss +0 -6
  180. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.component.ts +8 -0
  181. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.scss +10 -5
  182. package/src/components/flow-builder/modules/flow-node/flow-node.component.ts +17 -0
  183. package/src/components/flow-builder/modules/flow-node/flow-node.scss +10 -0
  184. package/src/components/form-actions/form-actions.component.ts +48 -2
  185. package/src/components/form-actions/form-actions.scss +1 -1
  186. package/src/components/form-group/form-group.component.ts +10 -3
  187. package/src/components/form-group/form-group.scss +37 -4
  188. package/src/components/form-group/form-group.test.ts +10 -0
  189. package/src/components/header/header.component.ts +11 -4
  190. package/src/components/header/header.scss +47 -5
  191. package/src/components/hover-container/hover-container.component.ts +4 -5
  192. package/src/components/icon/icon.component.ts +95 -9
  193. package/src/components/icon/icon.scss +70 -6
  194. package/src/components/icon/icon.test.ts +55 -0
  195. package/src/components/icon-picker/icon-picker.component.ts +35 -1
  196. package/src/components/inline-edit/inline-edit.component.ts +38 -8
  197. package/src/components/inline-edit/inline-edit.scss +128 -19
  198. package/src/components/input/input.component.ts +173 -297
  199. package/src/components/input/input.scss +65 -43
  200. package/src/components/input/input.test.ts +86 -4
  201. package/src/components/item/item.component.ts +12 -0
  202. package/src/components/item/item.scss +102 -3
  203. package/src/components/item/item.test.ts +23 -0
  204. package/src/components/key/key.component.ts +2 -2
  205. package/src/components/key/key.scss +11 -0
  206. package/src/components/key-value/index.ts +12 -0
  207. package/src/components/key-value/key-value.component.ts +160 -0
  208. package/src/components/key-value/key-value.scss +20 -0
  209. package/src/components/key-value/key-value.test.ts +22 -0
  210. package/src/components/markdown-editor/markdown-editor.component.ts +8 -1
  211. package/src/components/menu/menu.component.ts +21 -2
  212. package/src/components/menu/menu.scss +43 -23
  213. package/src/components/menu/menu.test.ts +33 -0
  214. package/src/components/menu-item/menu-item.component.ts +13 -2
  215. package/src/components/menu-item/menu-item.scss +56 -23
  216. package/src/components/menu-item/menu-item.test.ts +31 -0
  217. package/src/components/menu-item/submenu-controller.ts +25 -15
  218. package/src/components/menu-label/index.ts +12 -0
  219. package/src/components/menu-label/menu-label.component.ts +30 -0
  220. package/src/components/menu-label/menu-label.scss +18 -0
  221. package/src/components/nav-item/index.ts +12 -0
  222. package/src/components/nav-item/nav-item.component.ts +83 -0
  223. package/src/components/nav-item/nav-item.scss +128 -0
  224. package/src/components/nav-list/index.ts +12 -0
  225. package/src/components/nav-list/nav-list.component.ts +313 -0
  226. package/src/components/nav-list/nav-list.scss +87 -0
  227. package/src/components/nav-list/nav-list.test.ts +250 -0
  228. package/src/components/navbar/navbar.component.ts +235 -171
  229. package/src/components/navbar/navbar.scss +333 -169
  230. package/src/components/navbar/navbar.test.ts +63 -143
  231. package/src/components/page/page.component.ts +114 -29
  232. package/src/components/page/page.scss +223 -95
  233. package/src/components/page/page.test.ts +214 -3
  234. package/src/components/page-builder/page-builder.component.ts +51 -5
  235. package/src/components/page-builder/page-builder.scss +6 -1
  236. package/src/components/page-nav/page-nav.component.ts +25 -3
  237. package/src/components/page-nav/page-nav.scss +10 -2
  238. package/src/components/pagination/pagination.scss +1 -1
  239. package/src/components/panel/panel.component.ts +14 -13
  240. package/src/components/panel/panel.scss +14 -10
  241. package/src/components/panel/panel.test.ts +42 -0
  242. package/src/components/popup/popup.component.ts +20 -13
  243. package/src/components/popup/popup.test.ts +21 -1
  244. package/src/components/priority-list/priority-list.component.ts +157 -172
  245. package/src/components/priority-list/priority-list.scss +113 -17
  246. package/src/components/priority-list/priority-list.test.ts +301 -3
  247. package/src/components/progress-bar/progress-bar.component.ts +1 -1
  248. package/src/components/progress-bar/progress-bar.scss +16 -4
  249. package/src/components/progress-tile/progress-tile.scss +1 -1
  250. package/src/components/query-builder/query-builder.component.ts +85 -10
  251. package/src/components/query-builder/query-builder.scss +7 -1
  252. package/src/components/query-builder/query-builder.test.ts +40 -0
  253. package/src/components/radio/radio.component.ts +57 -18
  254. package/src/components/radio/radio.scss +101 -26
  255. package/src/components/radio-group/radio-group.component.ts +45 -7
  256. package/src/components/radio-group/radio-group.scss +17 -0
  257. package/src/components/radio-group/radio-group.test.ts +63 -2
  258. package/src/components/rating/rating.component.ts +23 -0
  259. package/src/components/rating/rating.scss +1 -1
  260. package/src/components/remarkd-editor/remarkd-editor.component.ts +60 -5
  261. package/src/components/remarkd-editor/remarkd-editor.scss +12 -4
  262. package/src/components/report-table/index.ts +12 -0
  263. package/src/components/report-table/report-format.test.ts +86 -0
  264. package/src/components/report-table/report-format.ts +72 -0
  265. package/src/components/report-table/report-math.test.ts +74 -0
  266. package/src/components/report-table/report-math.ts +252 -0
  267. package/src/components/report-table/report-table.component.ts +681 -0
  268. package/src/components/report-table/report-table.scss +328 -0
  269. package/src/components/report-table/report-table.test.ts +702 -0
  270. package/src/components/reveal/reveal.component.ts +15 -1
  271. package/src/components/reveal/reveal.scss +5 -0
  272. package/src/components/schedule-builder/schedule-builder.component.ts +23 -8
  273. package/src/components/scroll-container/scroll-container.component.ts +19 -1
  274. package/src/components/scroll-container/scroll-container.scss +6 -1
  275. package/src/components/select/select.component.ts +52 -36
  276. package/src/components/select/select.scss +42 -25
  277. package/src/components/select/select.test.ts +14 -2
  278. package/src/components/settings-container/settings-container.scss +18 -5
  279. package/src/components/sidebar/sidebar.component.ts +8 -1
  280. package/src/components/sidebar/sidebar.scss +6 -1
  281. package/src/components/skeleton/skeleton.component.ts +3 -3
  282. package/src/components/skeleton/skeleton.scss +6 -6
  283. package/src/components/skeleton/skeleton.test.ts +9 -0
  284. package/src/components/slash-menu/slash-menu.scss +1 -1
  285. package/src/components/slideout/slideout.component.ts +20 -3
  286. package/src/components/slideout/slideout.scss +13 -6
  287. package/src/components/slideout/slideout.test.ts +19 -0
  288. package/src/components/split-button/split-button.component.ts +1 -1
  289. package/src/components/split-pane/split-pane.component.ts +71 -8
  290. package/src/components/split-pane/split-pane.scss +145 -41
  291. package/src/components/split-pane/split-pane.test.ts +23 -3
  292. package/src/components/stat/stat.component.ts +209 -14
  293. package/src/components/stat/stat.scss +305 -5
  294. package/src/components/stat/stat.test.ts +143 -2
  295. package/src/components/status-indicator/status-indicator.scss +22 -21
  296. package/src/components/stepper/stepper.scss +3 -3
  297. package/src/components/tab/tab.component.ts +1 -0
  298. package/src/components/table/table.component.ts +12 -1
  299. package/src/components/table/table.scss +21 -13
  300. package/src/components/table/table.test.ts +17 -0
  301. package/src/components/tabs/tabs.component.ts +150 -37
  302. package/src/components/tabs/tabs.scss +48 -7
  303. package/src/components/tabs/tabs.test.ts +169 -0
  304. package/src/components/textarea/textarea.component.ts +25 -3
  305. package/src/components/textarea/textarea.scss +10 -0
  306. package/src/components/textarea/textarea.test.ts +8 -4
  307. package/src/components/theme-editor/theme-editor.scss +0 -6
  308. package/src/components/tile/tile.component.ts +32 -2
  309. package/src/components/tile/tile.scss +40 -7
  310. package/src/components/tile/tile.test.ts +10 -0
  311. package/src/components/toggle/toggle.component.ts +23 -7
  312. package/src/components/toggle/toggle.scss +36 -29
  313. package/src/components/toggle/toggle.test.ts +17 -0
  314. package/src/components/tooltip/tooltip.component.ts +3 -0
  315. package/src/components/tooltip/tooltip.scss +11 -6
  316. package/src/components/tooltip/tooltip.test.ts +12 -0
  317. package/src/components/translation-field/index.ts +12 -0
  318. package/src/components/translation-field/translation-field.component.ts +55 -0
  319. package/src/components/translation-field/translation-field.scss +101 -0
  320. package/src/components/translation-fields/index.ts +12 -0
  321. package/src/components/translation-fields/translation-fields.component.ts +80 -0
  322. package/src/components/translation-fields/translation-fields.scss +60 -0
  323. package/src/components/translation-grid/index.ts +12 -0
  324. package/src/components/translation-grid/translation-grid.component.ts +157 -0
  325. package/src/components/translation-grid/translation-grid.scss +138 -0
  326. package/src/components/translation-grid/translation-grid.test.ts +28 -0
  327. package/src/components/vertical-stepper/vertical-stepper.component.ts +35 -9
  328. package/src/components/vertical-stepper/vertical-stepper.scss +110 -39
  329. package/src/components/vertical-stepper/vertical-stepper.test.ts +35 -0
  330. package/src/components/well/well.scss +2 -2
  331. package/src/events/events.ts +2 -0
  332. package/src/events/zn-chart-click.ts +13 -0
  333. package/src/events/zn-report-change.ts +7 -0
  334. package/src/form-control.scss +36 -3
  335. package/src/internal/anchored-popover.ts +175 -0
  336. package/src/internal/animate.ts +19 -5
  337. package/src/internal/cosmic-border.ts +15 -0
  338. package/src/internal/form.ts +1 -1
  339. package/src/internal/hover-intent.ts +15 -0
  340. package/src/internal/input-modality.ts +15 -0
  341. package/src/internal/pointer-intent.ts +37 -0
  342. package/src/internal/reorder.ts +632 -0
  343. package/src/internal/scroll.ts +51 -3
  344. package/src/internal/selection-card.ts +1 -1
  345. package/src/internal/tab-indicator.ts +92 -0
  346. package/src/internal/table-sort.ts +25 -0
  347. package/src/internal/table-tabs.ts +108 -0
  348. package/src/internal/test-drag.ts +35 -0
  349. package/src/internal/theme-openbyte.test.ts +126 -0
  350. package/src/internal/theme.ts +4 -4
  351. package/src/internal/zinc-element.ts +2 -2
  352. package/src/selection-card.scss +25 -0
  353. package/src/types/web-test-runner-commands.d.ts +1 -0
  354. package/src/utilities/color.test.ts +43 -0
  355. package/src/utilities/color.ts +189 -0
  356. package/src/zinc.ts +14 -0
  357. package/.github/workflows/eleventy_build.yml +0 -42
  358. package/scss/themes/_aura.scss +0 -114
@@ -0,0 +1,37 @@
1
+ import '../../../dist/zn.min.js';
2
+ import { expect, fixture, html } from '@open-wc/testing';
3
+
4
+ describe('<zn-diff-row>', () => {
5
+ it('shows the item in both columns when unchanged', async () => {
6
+ const el = await fixture(html`<zn-diff-row caption="Passing score"></zn-diff-row>`);
7
+
8
+ const cells = el.shadowRoot!.querySelectorAll('[role="cell"]');
9
+ expect(cells).to.have.length(2);
10
+ expect(el.shadowRoot!.querySelector('.row__cell--absent')).to.not.exist;
11
+ expect(el.shadowRoot!.querySelector('zn-badge')).to.not.exist;
12
+ });
13
+
14
+ it('labels a changed row in the newer column', async () => {
15
+ const el = await fixture(html`<zn-diff-row caption="Passing score" change="changed"></zn-diff-row>`);
16
+
17
+ const badge = el.shadowRoot!.querySelector('[part="after"] zn-badge');
18
+ expect(badge?.textContent).to.equal('Changed');
19
+ expect(badge?.getAttribute('type')).to.equal('info');
20
+ });
21
+
22
+ it('shows a placeholder on the side an added or removed item is missing from', async () => {
23
+ const added = await fixture(html`<zn-diff-row caption="Tone" change="added"></zn-diff-row>`);
24
+ const removed = await fixture(html`<zn-diff-row caption="Survey" change="removed" after-placeholder="Removed"></zn-diff-row>`);
25
+
26
+ expect(added.shadowRoot!.querySelector('[part="before"]')!.classList.contains('row__cell--absent')).to.be.true;
27
+ expect(added.shadowRoot!.querySelector('[part="before"]')!.textContent).to.contain('Not in this version');
28
+ expect(removed.shadowRoot!.querySelector('[part="after"]')!.textContent).to.contain('Removed');
29
+ });
30
+
31
+ it('renders a heading across both columns', async () => {
32
+ const el = await fixture(html`<zn-diff-row caption="Opening" heading></zn-diff-row>`);
33
+
34
+ expect(el.shadowRoot!.querySelector('[role="rowheader"]')!.textContent).to.equal('Opening');
35
+ expect(el.shadowRoot!.querySelectorAll('[role="cell"]')).to.have.length(0);
36
+ });
37
+ });
@@ -0,0 +1,12 @@
1
+ import ZnDiffRow from './diff-row.component';
2
+
3
+ export * from './diff-row.component';
4
+ export default ZnDiffRow;
5
+
6
+ ZnDiffRow.define('zn-diff-row');
7
+
8
+ declare global {
9
+ interface HTMLElementTagNameMap {
10
+ 'zn-diff-row': ZnDiffRow;
11
+ }
12
+ }
@@ -58,7 +58,7 @@ export default class ZnDropdown extends ZincElement {
58
58
  @property({attribute: false}) containingElement?: HTMLElement;
59
59
 
60
60
  /** The distance in pixels from which to offset the panel away from the trigger */
61
- @property({type: Number}) distance: number = 0;
61
+ @property({type: Number}) distance: number = 4;
62
62
 
63
63
  /** The distance in pixels from which to offset the panel away from the trigger */
64
64
  @property({type: Number}) skidding: number = 0;
@@ -122,10 +122,8 @@ export default class ZnDropdown extends ZincElement {
122
122
  } else {
123
123
  this.panel.addEventListener('keydown', this.handleKeyDown);
124
124
  }
125
- document.addEventListener('keydown', this.handleDocumentKeyDown.bind(this));
126
- document.addEventListener('mousedown', this.handleDocumentMouseDown.bind(this));
127
-
128
- this.closeWatcher?.destroy();
125
+ document.addEventListener('keydown', this.handleDocumentKeyDown);
126
+ document.addEventListener('mousedown', this.handleDocumentMouseDown);
129
127
  }
130
128
 
131
129
  private removeOpenListeners() {
@@ -173,7 +171,7 @@ export default class ZnDropdown extends ZincElement {
173
171
  }
174
172
  }
175
173
 
176
- handleKeyDown(event: KeyboardEvent) {
174
+ handleKeyDown = (event: KeyboardEvent) => {
177
175
  if (this.open && event.key === 'Escape') {
178
176
  event.stopPropagation();
179
177
  this.hide().then(r => r);
@@ -182,7 +180,10 @@ export default class ZnDropdown extends ZincElement {
182
180
  }
183
181
 
184
182
  private async handleTriggerKeyDown(event: KeyboardEvent) {
185
- if ([' ', 'Enter'].includes(event.key)) {
183
+ const origin = event.composedPath()[0] as HTMLElement;
184
+ // A text-entry trigger needs Space/Enter for typing and form submission
185
+ const isTextEntry = origin.matches?.('input, textarea, [contenteditable]');
186
+ if ([' ', 'Enter'].includes(event.key) && !isTextEntry) {
186
187
  event.preventDefault();
187
188
  await this.handleTriggerClick();
188
189
  return;
@@ -234,7 +235,7 @@ export default class ZnDropdown extends ZincElement {
234
235
  this.updateAccessibleTrigger();
235
236
  }
236
237
 
237
- private handleDocumentMouseDown(event: MouseEvent) {
238
+ private handleDocumentMouseDown = (event: MouseEvent) => {
238
239
  const path = event.composedPath();
239
240
 
240
241
  if (this.containingElement && !path.includes(this.containingElement)) {
@@ -242,7 +243,7 @@ export default class ZnDropdown extends ZincElement {
242
243
  }
243
244
  }
244
245
 
245
- handleDocumentKeyDown(event: KeyboardEvent) {
246
+ handleDocumentKeyDown = (event: KeyboardEvent) => {
246
247
  if (event.key === 'Escape' && this.open && !this.closeWatcher) {
247
248
  event.stopPropagation();
248
249
  this.focusOnTrigger();
@@ -251,7 +252,8 @@ export default class ZnDropdown extends ZincElement {
251
252
  }
252
253
 
253
254
  if (event.key === 'Tab') {
254
- if (this.open) {
255
+ // Non-menu panels follow the trigger in tab order, so Tab moves into them and closes only once focus leaves
256
+ if (this.open && this.getMenu()) {
255
257
  this.hide().then(r => r);
256
258
  // Tabbing out of the menu resumes from the trigger; from the trigger, Tab moves on as usual
257
259
  if (this.panel?.assignedElements({flatten: true}).some(el => el.matches(':focus-within'))) {
@@ -7,3 +7,5 @@
7
7
  .dropdown::part(popup) {
8
8
  z-index: var(--zn-z-index-dropdown);
9
9
  }
10
+
11
+ @include wc.popover-motion('.dropdown');
@@ -1,8 +1,9 @@
1
1
  import {type CSSResultGroup, html, type PropertyValues, unsafeCSS} from 'lit';
2
2
  import {deepQuerySelectorAll, idSelector} from "../../utilities/query";
3
3
  import {FormControlController} from '../../internal/form';
4
+ import {HasSlotController} from "../../internal/slot";
4
5
  import {on} from "../../utilities/on";
5
- import {property, query} from 'lit/decorators.js';
6
+ import {property, query, state} from 'lit/decorators.js';
6
7
  import {Store} from "../../internal/storage";
7
8
  import Attachment from "./modules/attachment/attachment";
8
9
  import ContextMenu from "./modules/context-menu/context-menu";
@@ -12,6 +13,7 @@ import DragAndDrop from "./modules/drag-drop/drag-drop";
12
13
  import Emoji from "./modules/emoji/emoji";
13
14
  import HeadlessEmoji from "./modules/emoji/headless/headless-emoji";
14
15
  import ImageResize from "./modules/image-resize/image-resize";
16
+ import MergeField, {MergeFieldBlot, normaliseToken} from "./modules/merge-field/merge-field";
15
17
  import Quill from "quill";
16
18
  import QuillAI from "./modules/ai";
17
19
  import TimeTracking from "./modules/time-tracking/time-tracking";
@@ -23,7 +25,9 @@ import type {Range} from "quill";
23
25
  import type {ZincFormControl} from '../../internal/zinc-element';
24
26
  import type {ZnEditorInsertEvent} from "./modules/events/zn-editor-insert";
25
27
  import type ToolbarComponent from "./modules/toolbar/toolbar.component";
28
+ import type ZnEditorQuickAction from "./modules/context-menu/quick-action";
26
29
 
30
+ import formControlStyles from '../../form-control.scss';
27
31
  import styles from './editor.scss';
28
32
 
29
33
  export interface EditorFeatureConfig {
@@ -36,8 +40,12 @@ export interface EditorFeatureConfig {
36
40
  datesEnabled?: boolean;
37
41
  emojisEnabled?: boolean;
38
42
  codeEnabled?: boolean;
43
+ compact?: boolean;
39
44
  }
40
45
 
46
+ // Editing aid only: added to the document mode frame and left out of the saved HTML
47
+ const DOCUMENT_OUTLINES_ID = 'zn-editor-outlines';
48
+
41
49
  /**
42
50
  * @summary Short summary of the component's intended use.
43
51
  * @documentation https://zinc.style/components/editor
@@ -50,15 +58,17 @@ export interface EditorFeatureConfig {
50
58
  *
51
59
  * @slot - The default slot.
52
60
  * @slot example - An example slot.
61
+ * @slot help-text - Text under the editor. Alternatively, use the `help-text` attribute.
53
62
  *
54
63
  * @csspart base - The component's base wrapper.
55
64
  *
56
65
  * @cssproperty --example - An example CSS custom property.
57
66
  */
58
67
  export default class ZnEditor extends ZincElement implements ZincFormControl {
59
- static styles: CSSResultGroup = unsafeCSS(styles);
68
+ static styles: CSSResultGroup = [unsafeCSS(formControlStyles), unsafeCSS(styles)];
60
69
 
61
70
  private formControlController = new FormControlController(this, {});
71
+ private readonly hasSlotController = new HasSlotController(this, 'help-text');
62
72
 
63
73
  @query('#editor')
64
74
  private editor: HTMLElement;
@@ -73,6 +83,30 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
73
83
  @property() name: string;
74
84
  @property() value: string;
75
85
 
86
+ @property() placeholder = 'Compose your reply...';
87
+
88
+ /** Draws the editor as a form field: a bordered, resizable box under a small toolbar of bold, italic, link and lists. */
89
+ @property({type: Boolean, reflect: true}) compact = false;
90
+
91
+ /** Adds a Source button that switches to editing the raw HTML, which is submitted as written. */
92
+ @property({attribute: 'source', type: Boolean}) sourceEnabled = false;
93
+
94
+ /** Edits the HTML in place as a whole document, keeping layout the editor can't hold, such as a designed email. */
95
+ @property({attribute: 'document-mode', type: Boolean, reflect: true}) documentMode = false;
96
+
97
+ @query('.editor__document') private documentFrame: HTMLIFrameElement;
98
+
99
+ /** Shows only the content, without a toolbar or box, such as the source beside a translation. */
100
+ @property({type: Boolean, reflect: true}) readonly = false;
101
+
102
+ /** With `compact`, a short label inside the box ahead of the content, such as a language code. */
103
+ @property() prefix = '';
104
+
105
+ @state() private _sourceMode = false;
106
+
107
+ /** Text under the editor that describes how to use it. If you need to display HTML, use the `help-text` slot instead. */
108
+ @property({attribute: 'help-text'}) helpText = '';
109
+
76
110
  @property({attribute: 'interaction-type', type: String})
77
111
  interactionType: 'ticket' | 'chat' = 'chat';
78
112
 
@@ -90,6 +124,12 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
90
124
  @property({attribute: 'emojis', type: Boolean}) emojisEnabled: boolean = false;
91
125
  @property({attribute: 'code', type: Boolean}) codeEnabled: boolean = false;
92
126
  @property({attribute: 'ai', type: Boolean}) aiEnabled: boolean = false;
127
+
128
+ /**
129
+ * Shows `{{token}}` replacements as highlighted chips, labelled from the matching `context-items`
130
+ * quick action. The value still holds the raw tokens.
131
+ */
132
+ @property({attribute: 'merge-fields', type: Boolean}) mergeFieldsEnabled: boolean = false;
93
133
  @property({attribute: 'ai-path'}) aiPath: string = '';
94
134
 
95
135
  /**
@@ -110,6 +150,8 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
110
150
  private quillElement: Quill;
111
151
  private _content: string = '';
112
152
  private _selectionRange: Range = {index: 0, length: 0};
153
+ // in-flight attachment uploads; the leave-page prompt stays while any is running
154
+ private _pendingUploads = 0;
113
155
 
114
156
  get validity(): ValidityState {
115
157
  return this.editorHtml.validity;
@@ -170,6 +212,9 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
170
212
  Quill.register({'modules/imageResize': ImageResize}, true);
171
213
  Quill.register({'modules/contextMenu': ContextMenu}, true);
172
214
  Quill.register({'modules/dialog': Dialog}, true);
215
+ if (this.mergeFieldsEnabled) {
216
+ Quill.register({'formats/mergeField': MergeFieldBlot, 'modules/mergeField': MergeField}, true);
217
+ }
173
218
 
174
219
  /* AI Modules */
175
220
  if (this.aiEnabled) {
@@ -208,6 +253,7 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
208
253
  datesEnabled: this.datesEnabled,
209
254
  emojisEnabled: this.emojisEnabled,
210
255
  codeEnabled: this.codeEnabled,
256
+ compact: this.compact,
211
257
  };
212
258
 
213
259
  const quill = new Quill(this.editor, {
@@ -222,6 +268,9 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
222
268
  keyboard: {
223
269
  bindings: bindings
224
270
  },
271
+ ...(this.mergeFieldsEnabled && {
272
+ mergeField: {labels: this._mergeFieldLabels()}
273
+ }),
225
274
  dialog: {
226
275
  editorId: this.id
227
276
  },
@@ -244,10 +293,10 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
244
293
  ...(this.attachmentsEnabled && {
245
294
  attachment: {
246
295
  attachmentInput: this.getForm()?.querySelector('input[name="attachments"]'),
247
- onFileUploaded: () => {
248
- window.onbeforeunload = () => null;
249
- },
296
+ onFileUploaded: () => this._settleUpload(),
297
+ onFileUploadFailed: () => this._settleUpload(),
250
298
  upload: async (file: File) => {
299
+ this._pendingUploads++;
251
300
  window.onbeforeunload = () => 'You have unsaved changes. Are you sure you want to leave?';
252
301
 
253
302
  const fd = new FormData();
@@ -274,7 +323,8 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
274
323
  imageResize: {},
275
324
  history: {}
276
325
  },
277
- placeholder: 'Compose your reply...',
326
+ placeholder: this.placeholder,
327
+ readOnly: this.readonly,
278
328
  theme: 'snow',
279
329
  bounds: this.editor,
280
330
  });
@@ -408,12 +458,82 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
408
458
  const delta = quill.clipboard.convert({html: this.value});
409
459
  quill.setContents(delta, Quill.sources.SILENT);
410
460
 
461
+ if (this.documentMode) {
462
+ this._loadDocument(this.value ?? '');
463
+ }
464
+
411
465
  this.emit('zn-element-added', {detail: {element: this.editor}});
412
466
  super.firstUpdated(_changedProperties);
413
467
  }
414
468
 
469
+ private _toggleSource() {
470
+ const source = this.renderRoot.querySelector<HTMLTextAreaElement>('.editor__source')!;
471
+ if (!this._sourceMode) {
472
+ source.value = this.value ?? '';
473
+ } else if (this.documentMode) {
474
+ this._loadDocument(source.value);
475
+ } else {
476
+ // Back in the editor the HTML is reduced to what it can show
477
+ const delta = this.quillElement.clipboard.convert({html: source.value});
478
+ this.quillElement.setContents(delta, Quill.sources.USER);
479
+ }
480
+ this._sourceMode = !this._sourceMode;
481
+ }
482
+
483
+ private _loadDocument(html: string) {
484
+ const frame = this.documentFrame;
485
+ frame.addEventListener('load', () => {
486
+ const doc = frame.contentDocument!;
487
+ const outlines = doc.createElement('style');
488
+ outlines.id = DOCUMENT_OUTLINES_ID;
489
+ outlines.textContent = 'table,td,th{outline:1px dotted #d3d3d3;outline-offset:-1px}';
490
+ doc.head.append(outlines);
491
+ doc.designMode = 'on';
492
+ doc.addEventListener('input', () => this._handleDocumentInput(/<html[\s>]/i.test(html)));
493
+ this._fitDocument();
494
+ new ResizeObserver(() => this._fitDocument()).observe(doc.body);
495
+ }, {once: true});
496
+ frame.srcdoc = html;
497
+ }
498
+
499
+ // Grows to the content; the stylesheet's max-height caps it
500
+ private _fitDocument() {
501
+ const frame = this.documentFrame;
502
+ frame.style.height = `${frame.contentDocument?.documentElement.offsetHeight ?? 0}px`;
503
+ }
504
+
505
+ private _handleDocumentInput(wholeDocument: boolean) {
506
+ const doc = this.documentFrame.contentDocument!;
507
+ const root = doc.documentElement.cloneNode(true) as HTMLElement;
508
+ root.querySelector(`#${DOCUMENT_OUTLINES_ID}`)?.remove();
509
+ const doctype = doc.doctype ? `<!DOCTYPE ${doc.doctype.name}>\n` : '';
510
+ this.value = wholeDocument ? doctype + root.outerHTML : root.querySelector('body')!.innerHTML;
511
+ this.editorHtml.value = this.value;
512
+ this._cacheContent();
513
+ this.emit('zn-change');
514
+ }
515
+
516
+ private _handleSourceInput(e: Event) {
517
+ this.value = (e.target as HTMLTextAreaElement).value;
518
+ this.editorHtml.value = this.value;
519
+ this._cacheContent();
520
+ this.emit('zn-change');
521
+ }
522
+
523
+ private _mergeFieldLabels(): Record<string, string> {
524
+ const labels: Record<string, string> = {};
525
+ this.querySelectorAll<ZnEditorQuickAction>('zn-editor-quick-action[slot="context-items"]').forEach(action => {
526
+ if (action.content && action.label) {
527
+ labels[normaliseToken(action.content)] = action.label;
528
+ }
529
+ });
530
+ return labels;
531
+ }
532
+
415
533
  private _handleTextChange() {
416
- this.value = this.quillElement.getSemanticHTML();
534
+ if (this.documentMode) return;
535
+ // Quill writes every space as &nbsp;, which stops text wrapping; only runs of spaces need it
536
+ this.value = this.quillElement.getSemanticHTML().replace(/&nbsp;(?!&nbsp;)/g, ' ');
417
537
  this.editorHtml.value = this.value;
418
538
  this._cacheContent();
419
539
  this.emit('zn-change');
@@ -432,6 +552,13 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
432
552
  }
433
553
  }
434
554
 
555
+ private _settleUpload() {
556
+ this._pendingUploads--;
557
+ if (this._pendingUploads === 0) {
558
+ window.onbeforeunload = () => null;
559
+ }
560
+ }
561
+
435
562
  private _clearCachedContent() {
436
563
  if (this.storeKey && this._store) {
437
564
  this._store.remove(this.storeKey);
@@ -608,15 +735,36 @@ export default class ZnEditor extends ZincElement implements ZincFormControl {
608
735
 
609
736
  render() {
610
737
  return html`
611
- <zn-toolbar id="toolbar">
612
- <slot name="tools"></slot>
613
- </zn-toolbar>
738
+ <div class="editor__bar">
739
+ <zn-toolbar id="toolbar" ?data-source=${this._sourceMode || this.documentMode}>
740
+ <slot name="tools"></slot>
741
+ </zn-toolbar>
742
+ ${this.sourceEnabled && !this.readonly ? html`
743
+ <zn-button class="editor__source-toggle" color="transparent" size="small"
744
+ icon="${this._sourceMode ? 'pencil@lu' : 'code@lu'}" icon-size="16"
745
+ @click=${this._toggleSource}>${this._sourceMode ? 'Editor' : 'Source'}</zn-button>` : ''}
746
+ </div>
614
747
  <slot name="context-items" style="display: none;"></slot>
615
- <div id="editor" x-editor-id="${this.id}"></div>
748
+ <div class="editor__box ${this.prefix ? 'editor__box--prefixed' : ''}">
749
+ ${this.prefix ? html`<span class="editor__prefix">${this.prefix}</span>` : ''}
750
+ <div id="editor" x-editor-id="${this.id}" ?hidden=${this._sourceMode || this.documentMode}></div>
751
+ ${this.documentMode ? html`
752
+ <iframe class="editor__document" sandbox="allow-same-origin" title="${this.placeholder}"
753
+ ?hidden=${this._sourceMode}></iframe>` : ''}
754
+ ${this.sourceEnabled ? html`
755
+ <textarea class="editor__source" spellcheck="false" ?hidden=${!this._sourceMode}
756
+ @input=${this._handleSourceInput}></textarea>` : ''}
757
+ </div>
616
758
  <input type="text" id="editorHtml" name="${this.name}" value="${this.value}" style="display: none;">
617
759
  <div id="action-container" class="ql-toolbar ql-snow">
618
760
  <slot name="actions"></slot>
619
761
  </div>
762
+ <div class="form-control form-control--medium form-control--has-help-text"
763
+ ?hidden=${!this.helpText && !this.hasSlotController.test('help-text')}>
764
+ <div part="form-control-help-text" class="form-control__help-text">
765
+ <slot name="help-text">${this.helpText}</slot>
766
+ </div>
767
+ </div>
620
768
  `;
621
769
  }
622
770
  }
@@ -141,7 +141,7 @@
141
141
 
142
142
  :host #toolbar zn-dropdown zn-menu zn-menu-item[checked] .menu-item {
143
143
  background-color: rgba(var(--zn-panel-highlight), var(--zn-panel-highlight-opacity));
144
- color: rgb(var(--zn-primary));
144
+ color: var(--zn-color-primary-fg, rgb(var(--zn-primary)));
145
145
  }
146
146
 
147
147
  :host .ql-editor hr,
@@ -153,6 +153,255 @@
153
153
  opacity: 1;
154
154
  }
155
155
 
156
+ :host .ql-editor .ql-merge-field {
157
+ padding: 0 6px;
158
+ border-radius: var(--zn-input-border-radius-medium);
159
+ background-color: rgba(var(--zn-primary), 0.08);
160
+ color: rgb(var(--zn-primary));
161
+ font-weight: var(--zn-font-weight-semibold);
162
+ white-space: nowrap;
163
+ }
164
+
165
+ .editor__bar {
166
+ display: flex;
167
+ align-items: center;
168
+ padding-inline: var(--editor-gutter);
169
+
170
+ #toolbar {
171
+ flex: 1;
172
+ padding-inline: 0;
173
+
174
+ // Keeps its space so switching to the source doesn't move the box
175
+ &[data-source] {
176
+ visibility: hidden;
177
+ }
178
+ }
179
+
180
+ .editor__source-toggle {
181
+ margin-left: auto;
182
+ }
183
+ }
184
+
185
+ .editor__box {
186
+ position: relative;
187
+ display: flex;
188
+ flex: 1;
189
+ flex-direction: column;
190
+ min-height: 0;
191
+ }
192
+
193
+ .editor__prefix {
194
+ position: absolute;
195
+ z-index: 1;
196
+ top: var(--zn-spacing-x-small);
197
+ inset-inline-start: calc(var(--zn-spacing-unit, 8px) * 1.5);
198
+ color: rgb(var(--zn-text));
199
+ font-size: 12px;
200
+ font-weight: 700;
201
+ line-height: calc(var(--zn-input-font-size-medium) * 1.5);
202
+ pointer-events: none;
203
+ }
204
+
205
+ .editor__document {
206
+ display: block;
207
+ width: 100%;
208
+ min-height: 24rem;
209
+ max-height: var(--editor-max-height, 70vh);
210
+ border: none;
211
+ background-color: #fff;
212
+
213
+ &[hidden] {
214
+ display: none;
215
+ }
216
+ }
217
+
218
+ .editor__source {
219
+ display: block;
220
+ width: 100%;
221
+ padding: var(--zn-spacing-x-small) var(--zn-spacing-small);
222
+ border: none;
223
+ outline: none;
224
+ resize: vertical;
225
+ font-family: var(--zn-font-mono);
226
+ font-size: var(--zn-font-size-small);
227
+ color: rgb(var(--zn-text));
228
+ background-color: var(--zn-input-background-color);
229
+
230
+ &[hidden] {
231
+ display: none;
232
+ }
233
+ }
234
+
235
+ :host([compact]) {
236
+ min-height: 0;
237
+ max-height: none;
238
+ flex: none;
239
+ overflow: visible;
240
+ gap: calc(var(--zn-spacing-unit, 8px) * 1.5);
241
+ background-color: transparent;
242
+
243
+ .editor__bar {
244
+ --zn-button-height-small: 24px;
245
+ --zn-button-font-size-small: 12px;
246
+ padding-inline: 0;
247
+
248
+ #toolbar {
249
+ padding: 0;
250
+ }
251
+
252
+ .editor__source-toggle::part(base) {
253
+ color: rgb(var(--zn-color-muted-text));
254
+ }
255
+ }
256
+
257
+ #editor,
258
+ .editor__source,
259
+ .editor__document {
260
+ box-sizing: border-box;
261
+ flex: 1 0 auto;
262
+ height: var(--editor-height, 224px);
263
+ min-height: 6rem;
264
+ overflow: auto;
265
+ resize: vertical;
266
+ border: solid var(--zn-input-border-width) var(--zn-input-border-color);
267
+ border-radius: var(--zn-input-border-radius-medium);
268
+ background-color: var(--zn-input-background-color);
269
+ transition: var(--zn-transition-fast) border, var(--zn-transition-fast) box-shadow;
270
+
271
+ &:hover {
272
+ border-color: var(--zn-input-border-color-hover);
273
+ }
274
+
275
+ &:focus-within,
276
+ &:focus {
277
+ border-color: var(--zn-input-border-color-focus);
278
+ box-shadow: 0 0 0 var(--zn-focus-ring-width) var(--zn-input-focus-ring-color);
279
+ }
280
+ }
281
+
282
+ #editor[hidden] {
283
+ display: none;
284
+ }
285
+
286
+ .ql-container {
287
+ padding: 0;
288
+ }
289
+
290
+ // Fills any height the host is given, such as a translation field's row
291
+ .editor__box {
292
+ flex: 1 0 auto;
293
+ }
294
+
295
+ .ql-editor {
296
+ padding: var(--zn-spacing-x-small) calc(var(--zn-spacing-unit, 8px) * 1.5);
297
+ font-size: var(--zn-input-font-size-medium);
298
+ line-height: 1.5;
299
+ background-color: transparent;
300
+
301
+ > * + * {
302
+ margin-top: var(--zn-spacing-x-small);
303
+ }
304
+ }
305
+
306
+ .ql-editor.ql-blank:before {
307
+ left: calc(var(--zn-spacing-unit, 8px) * 1.5);
308
+ right: calc(var(--zn-spacing-unit, 8px) * 1.5);
309
+ font-style: normal;
310
+ color: var(--zn-input-placeholder-color);
311
+ }
312
+
313
+ // Never shorter than the plain editor, however short the document
314
+ .editor__document {
315
+ min-height: var(--editor-height, 224px);
316
+ }
317
+
318
+ // No box of its own, so an empty actions row adds no gap
319
+ #action-container {
320
+ display: contents;
321
+ }
322
+
323
+ .form-control__help-text {
324
+ margin-top: 0;
325
+ }
326
+ }
327
+
328
+ // The prefix's gutter: its width, and the space either side of it
329
+ :host([compact]) .editor__box--prefixed {
330
+ .ql-editor,
331
+ .editor__source {
332
+ padding-inline-start: calc(var(--zn-spacing-unit, 8px) * 3 + 32px);
333
+ }
334
+
335
+ .ql-editor.ql-blank:before {
336
+ inset-inline-start: calc(var(--zn-spacing-unit, 8px) * 3 + 32px);
337
+ }
338
+ }
339
+
340
+ // Quill pins text and list markers to the left whatever the direction
341
+ :host([dir="rtl"]) .ql-editor {
342
+ text-align: right;
343
+
344
+ li {
345
+ padding-left: 0;
346
+ padding-right: 1.5em;
347
+ }
348
+
349
+ li > .ql-ui:before {
350
+ margin-left: 0.3em;
351
+ margin-right: -1.5em;
352
+ text-align: left;
353
+ }
354
+ }
355
+
356
+ .form-control[hidden] {
357
+ display: none;
358
+ }
359
+
360
+ // Content only, such as a translation's source shown beside it
361
+ :host([readonly]) {
362
+ min-height: 0;
363
+ max-height: none;
364
+ flex: none;
365
+ overflow: visible;
366
+ background-color: transparent;
367
+
368
+ .editor__bar,
369
+ #action-container {
370
+ display: none;
371
+ }
372
+
373
+ .editor__box {
374
+ display: block;
375
+ }
376
+
377
+ #editor {
378
+ flex: none;
379
+ height: auto;
380
+ border: 0;
381
+ background-color: transparent;
382
+ box-shadow: none;
383
+ resize: none;
384
+ }
385
+
386
+ .ql-container {
387
+ padding: 0;
388
+ }
389
+
390
+ .ql-editor {
391
+ height: auto;
392
+ padding: 0;
393
+ overflow: visible;
394
+ line-height: 1.5;
395
+ color: inherit;
396
+ font-size: inherit;
397
+ background-color: transparent;
398
+
399
+ > * + * {
400
+ margin-top: var(--zn-spacing-x-small);
401
+ }
402
+ }
403
+ }
404
+
156
405
  #toolbar {
157
406
  padding-inline: var(--editor-gutter);
158
407
  }