@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,141 @@
1
+ @use "../../wc";
2
+
3
+ :host {
4
+ display: block;
5
+ }
6
+
7
+ .color-picker {
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: 12px;
11
+ width: var(--zn-color-picker-width, 280px);
12
+ padding: 12px;
13
+ background: var(--zn-panel-background-color, rgb(var(--zn-panel)));
14
+ border: 1px solid rgb(var(--zn-border-color));
15
+ border-radius: var(--zn-border-radius-medium);
16
+ box-shadow: var(--zn-shadow-large);
17
+ font-family: var(--zn-font-family-sans);
18
+ }
19
+
20
+ .color-picker__area {
21
+ position: relative;
22
+ height: 152px;
23
+ border-radius: var(--zn-border-radius);
24
+ cursor: crosshair;
25
+ touch-action: none;
26
+ background-image: linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
27
+
28
+ &:focus-visible {
29
+ outline: none;
30
+ box-shadow: 0 0 0 var(--zn-focus-ring-width) var(--zn-input-focus-ring-color);
31
+ }
32
+ }
33
+
34
+ // Not @extend: a merged selector list holding an unknown vendor pseudo-element is dropped whole.
35
+ @mixin thumb {
36
+ border: 2px solid #fff;
37
+ border-radius: 50%;
38
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, .35), 0 1px 3px rgba(0, 0, 0, .4);
39
+ }
40
+
41
+ .color-picker__dot {
42
+ @include thumb;
43
+ position: absolute;
44
+ width: 14px;
45
+ height: 14px;
46
+ margin: -7px 0 0 -7px;
47
+ pointer-events: none;
48
+ }
49
+
50
+ .color-picker__hue {
51
+ appearance: none;
52
+ width: 100%;
53
+ height: 12px;
54
+ margin: 0;
55
+ border-radius: 999px;
56
+ cursor: pointer;
57
+ background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
58
+
59
+ &::-webkit-slider-thumb {
60
+ @include thumb;
61
+ appearance: none;
62
+ width: 16px;
63
+ height: 16px;
64
+ background: transparent;
65
+ }
66
+
67
+ &::-moz-range-thumb {
68
+ @include thumb;
69
+ width: 12px;
70
+ height: 12px;
71
+ background: transparent;
72
+ }
73
+
74
+ &:focus-visible {
75
+ outline: none;
76
+ box-shadow: 0 0 0 var(--zn-focus-ring-width) var(--zn-input-focus-ring-color);
77
+ }
78
+ }
79
+
80
+ .color-picker__values {
81
+ display: flex;
82
+ flex-direction: column;
83
+ gap: 8px;
84
+ }
85
+
86
+ .color-picker__row {
87
+ display: grid;
88
+ grid-template-columns: 48px 1fr;
89
+ align-items: center;
90
+ gap: 8px;
91
+ }
92
+
93
+ .color-picker__row-label {
94
+ font-size: 11px;
95
+ font-weight: var(--zn-font-weight-semibold);
96
+ line-height: 1;
97
+ letter-spacing: 0.04em;
98
+ color: var(--zn-input-placeholder-color);
99
+ }
100
+
101
+ .color-picker__trio {
102
+ display: grid;
103
+ grid-template-columns: repeat(3, minmax(0, 1fr));
104
+ gap: 4px;
105
+ }
106
+
107
+ .color-picker__field {
108
+ width: 100%;
109
+ min-width: 0;
110
+ height: var(--zn-input-height-small);
111
+ padding: 0 8px;
112
+ font-family: var(--zn-font-family-mono);
113
+ font-size: 12px;
114
+ font-variant-numeric: tabular-nums;
115
+ text-align: center;
116
+ color: var(--zn-input-color);
117
+ background: var(--zn-input-background-color);
118
+ border: solid var(--zn-input-border-width) var(--zn-input-border-color);
119
+ border-radius: var(--zn-input-border-radius-small);
120
+ box-shadow: var(--zn-input-shadow, none);
121
+ transition: var(--zn-transition-fast) border-color, var(--zn-transition-fast) box-shadow;
122
+
123
+ &:hover {
124
+ border-color: var(--zn-input-border-color-hover);
125
+ }
126
+
127
+ &:focus {
128
+ outline: none;
129
+ border-color: var(--zn-input-border-color-focus);
130
+ box-shadow: 0 0 0 var(--zn-focus-ring-width) var(--zn-input-focus-ring-color);
131
+ }
132
+
133
+ &[aria-invalid='true'] {
134
+ color: var(--zn-color-danger-fg);
135
+ border-color: var(--zn-input-border-color-invalid);
136
+ }
137
+ }
138
+
139
+ .color-picker__row--hex .color-picker__field {
140
+ text-align: left;
141
+ }
@@ -0,0 +1,57 @@
1
+ import '../../../dist/zn.min.js';
2
+ import {expect, fixture, html, oneEvent} from '@open-wc/testing';
3
+ import type ZnColorPicker from './color-picker.component';
4
+
5
+ const field = (el: ZnColorPicker, key: string) => el.shadowRoot!.querySelector<HTMLInputElement>(`[data-k="${key}"]`)!;
6
+
7
+ const type = (input: HTMLInputElement, value: string) => {
8
+ input.focus();
9
+ input.value = value;
10
+ input.dispatchEvent(new Event('input', {bubbles: true, composed: true}));
11
+ };
12
+
13
+ describe('<zn-color-picker>', () => {
14
+ it('shows the colour in every format', async () => {
15
+ const el = await fixture<ZnColorPicker>(html`<zn-color-picker value="rgb(8, 94, 253)"></zn-color-picker>`);
16
+
17
+ expect(el.value).to.equal('#085EFD');
18
+ expect(field(el, 'hex').value).to.equal('#085EFD');
19
+ expect([field(el, 'r').value, field(el, 'g').value, field(el, 'b').value]).to.deep.equal(['8', '94', '253']);
20
+ expect([field(el, 'h').value, field(el, 's').value, field(el, 'l').value]).to.deep.equal(['219', '98', '51']);
21
+ expect([field(el, 'ol').value, field(el, 'oc').value, field(el, 'oh').value]).to.deep.equal(['54.8', '0.247', '262']);
22
+ });
23
+
24
+ it('updates the other rows when one is edited and switches to its format', async () => {
25
+ const el = await fixture<ZnColorPicker>(html`<zn-color-picker value="#085EFD"></zn-color-picker>`);
26
+
27
+ const changed = oneEvent(el, 'zn-input');
28
+ type(field(el, 'g'), '200');
29
+ await changed;
30
+ await el.updateComplete;
31
+
32
+ expect(el.value).to.equal('#08C8FD');
33
+ expect(el.format).to.equal('rgb');
34
+ expect(field(el, 'hex').value).to.equal('#08C8FD');
35
+ expect(field(el, 'g').value).to.equal('200');
36
+ });
37
+
38
+ it('marks an out-of-range value red without changing the colour', async () => {
39
+ const el = await fixture<ZnColorPicker>(html`<zn-color-picker value="#085EFD"></zn-color-picker>`);
40
+
41
+ type(field(el, 'r'), '300');
42
+ await el.updateComplete;
43
+
44
+ expect(field(el, 'r').getAttribute('aria-invalid')).to.equal('true');
45
+ expect(el.value).to.equal('#085EFD');
46
+ });
47
+
48
+ it('moves brightness with the arrow keys', async () => {
49
+ const el = await fixture<ZnColorPicker>(html`<zn-color-picker value="#FFFFFF"></zn-color-picker>`);
50
+ const area = el.shadowRoot!.querySelector<HTMLElement>('.color-picker__area')!;
51
+
52
+ area.dispatchEvent(new KeyboardEvent('keydown', {key: 'ArrowDown'}));
53
+ await el.updateComplete;
54
+
55
+ expect(el.value).to.equal('#FCFCFC');
56
+ });
57
+ });
@@ -0,0 +1,12 @@
1
+ import ZnColorPicker from './color-picker.component';
2
+
3
+ export * from './color-picker.component';
4
+ export default ZnColorPicker;
5
+
6
+ ZnColorPicker.define('zn-color-picker');
7
+
8
+ declare global {
9
+ interface HTMLElementTagNameMap {
10
+ 'zn-color-picker': ZnColorPicker;
11
+ }
12
+ }
@@ -48,6 +48,9 @@ export default class ZnCols extends ZincElement {
48
48
 
49
49
  @property({attribute: 'mc', type: Number, reflect: true}) maxColumns: number = 0;
50
50
 
51
+ /** Minimum width in px of a one-unit column before the row wraps; a column of layout `n` asks for n times this. Defaults to 250. */
52
+ @property({type: Number}) basis: number;
53
+
51
54
  @property({attribute: 'no-gap', type: Boolean}) noGap: boolean = false;
52
55
 
53
56
  @property({type: Boolean}) border: boolean = false;
@@ -81,6 +84,13 @@ export default class ZnCols extends ZincElement {
81
84
 
82
85
  protected updated(changed: PropertyValues<this>) {
83
86
  super.updated(changed);
87
+ if (changed.has('basis')) {
88
+ if (this.basis > 0) {
89
+ this.style.setProperty('--zn-col-basis', `${this.basis}px`);
90
+ } else {
91
+ this.style.removeProperty('--zn-col-basis');
92
+ }
93
+ }
84
94
  this.markRowEnds();
85
95
  }
86
96
 
@@ -182,4 +182,21 @@ describe('<zn-cols>', () => {
182
182
  expect(ruleOf('#d')).to.equal('none');
183
183
  });
184
184
  });
185
+
186
+ it('sizes columns from the basis attribute', async () => {
187
+ const el = await cols(`
188
+ <zn-cols layout="1,2" basis="140">
189
+ <div id="one"></div>
190
+ <div id="two"></div>
191
+ </zn-cols>`);
192
+
193
+ expect(getComputedStyle(el.querySelector('#one')!).flexBasis).to.equal('140px');
194
+ expect(getComputedStyle(el.querySelector('#two')!).flexBasis).to.equal('280px');
195
+ });
196
+
197
+ it('keeps the default basis without the attribute', async () => {
198
+ const el = await cols(`<zn-cols layout="1"><div id="one"></div></zn-cols>`);
199
+
200
+ expect(getComputedStyle(el.querySelector('#one')!).flexBasis).to.equal('250px');
201
+ });
185
202
  });
@@ -6,6 +6,7 @@ import {ifDefined} from "lit/directives/if-defined.js";
6
6
  import {property, query, state} from 'lit/decorators.js';
7
7
  import ZincElement from "../../internal/zinc-element";
8
8
  import ZnDialog from "../dialog";
9
+ import type ZnButton from "../button";
9
10
 
10
11
  import styles from './confirm.scss';
11
12
 
@@ -66,11 +67,11 @@ export default class ZnConfirm extends ZincElement {
66
67
 
67
68
  @property() content: string = '';
68
69
 
69
- @property() confirmText: string = "Confirm";
70
+ @property({attribute: 'confirm-text'}) confirmText: string = "Confirm";
70
71
 
71
- @property() cancelText: string = "Cancel";
72
+ @property({attribute: 'cancel-text'}) cancelText: string = "Cancel";
72
73
 
73
- @property() closeText: string = "Close";
74
+ @property({attribute: 'close-text'}) closeText: string = "Close";
74
75
 
75
76
  @property({type: Boolean, attribute: 'hide-icon'}) hideIcon: boolean = false;
76
77
 
@@ -102,6 +103,8 @@ export default class ZnConfirm extends ZincElement {
102
103
 
103
104
  private submitted: HTMLFormElement | null = null;
104
105
 
106
+ private generatedForm: HTMLFormElement | null = null;
107
+
105
108
  protected firstUpdated(_changedProperties: PropertyValues) {
106
109
  super.firstUpdated(_changedProperties);
107
110
  if (this.open) {
@@ -132,11 +135,13 @@ export default class ZnConfirm extends ZincElement {
132
135
  });
133
136
  }
134
137
 
135
- show = (event: Event | undefined = undefined) => {
138
+ show = async (event: Event | undefined = undefined) => {
136
139
  const trigger = event?.target as HTMLButtonElement
137
140
  if (trigger?.disabled) return;
138
141
  this.reset();
139
142
  this.dialog.show();
143
+ await this.updateComplete;
144
+ this.renderRoot.querySelector<ZnButton>('zn-button[dialog-closer]')?.button?.focus();
140
145
  }
141
146
 
142
147
  hide() {
@@ -169,7 +174,7 @@ export default class ZnConfirm extends ZincElement {
169
174
  * The console dispatches the pagelet lifecycle on the form it submitted. Without it the loading
170
175
  * state only ends when a response happens to reload the page, so every failure hangs the dialog.
171
176
  */
172
- private settle = (event: Event) => {
177
+ private settle = async (event: Event) => {
173
178
  const response = (event as CustomEvent<{ response?: PageletResponse }>).detail?.response;
174
179
  this.stopWatching();
175
180
  if (event.type === 'error' || this.responseFailed(response)) {
@@ -179,6 +184,8 @@ export default class ZnConfirm extends ZincElement {
179
184
  if (this.dialog?.closer) {
180
185
  this.dialog.closer.disabled = false;
181
186
  }
187
+ await this.updateComplete;
188
+ this.renderRoot.querySelector<ZnButton>('zn-button[dialog-closer]')?.button?.focus();
182
189
  return;
183
190
  }
184
191
  this.hide();
@@ -237,7 +244,7 @@ export default class ZnConfirm extends ZincElement {
237
244
  <zn-button outline color="${this.type}" slot="footer" dialog-closer disabled=${this.loading || nothing}>
238
245
  ${this.cancelText}
239
246
  </zn-button>
240
- <zn-button color="${this.type}" slot="footer" @click="${this.submitDialog}" disabled=${this.loading || nothing}>
247
+ <zn-button color="${this.type}" slot="footer" @click="${this.submitDialog}" ?processing=${this.loading}>
241
248
  ${this.confirmText}
242
249
  </zn-button>`}
243
250
 
@@ -246,10 +253,17 @@ export default class ZnConfirm extends ZincElement {
246
253
  }
247
254
 
248
255
  submitDialog() {
256
+ if (this.loading) return;
257
+
258
+ // Rebuilt per submit: a re-rendered list can reuse this element for another row with a different action
259
+ this.generatedForm?.remove();
260
+ this.generatedForm = null;
261
+
249
262
  // get the form from the slot
250
263
  let form = this.querySelector('form');
251
264
  if (!form && this.action) {
252
265
  form = document.createElement('form') as HTMLFormElement;
266
+ this.generatedForm = form;
253
267
  form.action = this.action;
254
268
  form.method = 'POST';
255
269
 
@@ -61,6 +61,15 @@ describe('<zn-confirm-modal>', () => {
61
61
  expect(confirm.shadowRoot!.textContent).to.contain('Loading');
62
62
  });
63
63
 
64
+ it('keeps the confirm button focusable while loading', async () => {
65
+ const {confirm} = await submittedConfirm();
66
+
67
+ const buttons = confirm.shadowRoot!.querySelectorAll('zn-button[slot="footer"]');
68
+ expect(buttons[0].hasAttribute('disabled')).to.be.true;
69
+ expect(buttons[1].hasAttribute('disabled')).to.be.false;
70
+ expect(buttons[1].hasAttribute('processing')).to.be.true;
71
+ });
72
+
64
73
  it('reports failure when the response carries a danger alert', async () => {
65
74
  const {confirm, form, dialog} = await submittedConfirm();
66
75
 
@@ -75,6 +84,16 @@ describe('<zn-confirm-modal>', () => {
75
84
  expect(closer(dialog).disabled).to.be.false;
76
85
  });
77
86
 
87
+ it('focuses cancel when opened', async () => {
88
+ const confirm = await fixture<HTMLElement>(html`<zn-confirm caption="Deploy"></zn-confirm>`);
89
+
90
+ await (confirm as never as {show: () => Promise<void>}).show();
91
+
92
+ const cancel = confirm.shadowRoot!.querySelector('zn-button[dialog-closer]');
93
+ expect(cancel!.textContent!.trim()).to.equal('Cancel');
94
+ expect(confirm.shadowRoot!.activeElement).to.equal(cancel);
95
+ });
96
+
78
97
  it('offers only a close button once the request has failed', async () => {
79
98
  const {confirm, form} = await submittedConfirm();
80
99
 
@@ -85,6 +104,7 @@ describe('<zn-confirm-modal>', () => {
85
104
  expect(buttons.length).to.equal(1);
86
105
  expect(buttons[0].textContent!.trim()).to.equal('Close');
87
106
  expect(buttons[0].hasAttribute('dialog-closer')).to.be.true;
107
+ expect(confirm.shadowRoot!.activeElement).to.equal(buttons[0]);
88
108
  });
89
109
 
90
110
  it('reports failure when the request errors', async () => {
@@ -117,4 +137,36 @@ describe('<zn-confirm-modal>', () => {
117
137
 
118
138
  expect(confirm.shadowRoot!.textContent).to.not.contain('Failed');
119
139
  });
140
+ it('submits to its current action after the action changes', async () => {
141
+ const confirm = await fixture<HTMLElement & {action: string; updateComplete: Promise<void>; show: () => void}>(
142
+ html`<zn-confirm caption="Delete" action="/items/1/delete"></zn-confirm>`);
143
+ const posted: string[] = [];
144
+ document.addEventListener('submit', e => {
145
+ e.preventDefault();
146
+ posted.push(new URL((e.target as HTMLFormElement).action).pathname);
147
+ });
148
+ const submit = async () => {
149
+ confirm.show();
150
+ await confirm.updateComplete;
151
+ click(confirm.shadowRoot!.querySelectorAll('zn-button[slot="footer"]')[1]);
152
+ };
153
+
154
+ await submit();
155
+ confirm.action = '/items/2/delete';
156
+ await confirm.updateComplete;
157
+ await submit();
158
+
159
+ expect(posted).to.deep.equal(['/items/1/delete', '/items/2/delete']);
160
+ });
161
+
162
+ it('labels its buttons from the dashed text attributes', async () => {
163
+ const confirm = await fixture<HTMLElement & {updateComplete: Promise<void>}>(html`
164
+ <zn-confirm confirm-text="Archive" cancel-text="Keep"></zn-confirm>
165
+ `);
166
+ await confirm.updateComplete;
167
+
168
+ const buttons = confirm.shadowRoot!.querySelectorAll('zn-button[slot="footer"]');
169
+ expect(buttons[0].textContent!.trim()).to.equal('Keep');
170
+ expect(buttons[1].textContent!.trim()).to.equal('Archive');
171
+ });
120
172
  });
@@ -3,6 +3,7 @@ import {deepQuerySelectorAll} from "../../utilities/query";
3
3
  import {HasSlotController} from "../../internal/slot";
4
4
  import {html, unsafeCSS} from 'lit';
5
5
  import {htmlToText, looksLikeHtml} from './html-text';
6
+ import {ifDefined} from "lit/directives/if-defined.js";
6
7
  import {MutationController} from '@lit-labs/observers/mutation-controller.js';
7
8
  import {property, queryAssignedNodes, queryAsync, state} from 'lit/decorators.js';
8
9
  import {sanitizeHtml} from '../../utilities/sanitize-html';
@@ -82,6 +83,7 @@ export default class ContentBlock extends ZincElement {
82
83
  connectedCallback() {
83
84
  super.connectedCallback();
84
85
  this.iframe.then((iframe) => {
86
+ if (!iframe) return;
85
87
  if (iframe.contentDocument) {
86
88
  const div = this.htmlNodes[0] as HTMLDivElement;
87
89
  if (div) {
@@ -109,6 +111,23 @@ export default class ContentBlock extends ZincElement {
109
111
  super.disconnectedCallback();
110
112
  }
111
113
 
114
+ private _handleHeaderKeyDown(e: KeyboardEvent) {
115
+ // Keys from the header's own actions belong to them
116
+ if (e.target !== e.currentTarget || (e.key !== 'Enter' && e.key !== ' ')) {
117
+ return;
118
+ }
119
+
120
+ e.preventDefault();
121
+ this._collapseContent(e);
122
+ }
123
+
124
+ private _handleReplyKeyDown(e: KeyboardEvent) {
125
+ if (e.key === 'Enter' || e.key === ' ') {
126
+ e.preventDefault();
127
+ (e.currentTarget as HTMLElement).click();
128
+ }
129
+ }
130
+
112
131
  private _collapseContent(e: Event) {
113
132
  if (this.noCollapse) {
114
133
  return;
@@ -136,7 +155,7 @@ export default class ContentBlock extends ZincElement {
136
155
  private _toggleText() {
137
156
  const textContent = this.shadowRoot?.querySelector('.text-content') as HTMLDivElement | null;
138
157
  this.iframe.then((iframe) => {
139
- if (textContent) {
158
+ if (iframe && textContent) {
140
159
  iframe.classList.add('hidden');
141
160
  textContent.classList.remove('hidden');
142
161
  }
@@ -146,7 +165,7 @@ export default class ContentBlock extends ZincElement {
146
165
  private _toggleHtml() {
147
166
  const textContent = this.shadowRoot?.querySelector('.text-content') as HTMLDivElement | null;
148
167
  this.iframe.then((iframe) => {
149
- if (textContent) {
168
+ if (iframe && textContent) {
150
169
  iframe.classList.remove('hidden');
151
170
  textContent.classList.add('hidden');
152
171
  setTimeout(() => this._resizeIframe(iframe), 0);
@@ -230,7 +249,12 @@ export default class ContentBlock extends ZincElement {
230
249
  'content-block--collapsible': !this.noCollapse
231
250
  })}">
232
251
 
233
- <div class="content-block-header" @click="${this._collapseContent}">
252
+ <div class="content-block-header"
253
+ role="${ifDefined(this.noCollapse ? undefined : 'button')}"
254
+ tabindex="${ifDefined(this.noCollapse ? undefined : '0')}"
255
+ aria-expanded="${ifDefined(this.noCollapse ? undefined : String(!this.short))}"
256
+ @click="${this._collapseContent}"
257
+ @keydown="${this._handleHeaderKeyDown}">
234
258
  <div class="content-block-header__icon">
235
259
  <slot name="icon">
236
260
  <zn-icon src="${this.avatar}"
@@ -270,13 +294,16 @@ export default class ContentBlock extends ZincElement {
270
294
  </div>
271
295
 
272
296
  <zn-sp no-gap flush-x flush-t>
273
- <iframe class="${classMap({'hidden': !initialShowHtml})}" title="Content block HTML preview"></iframe>
297
+ ${hasHtmlSlot ? html`
298
+ <iframe class="${classMap({'hidden': !initialShowHtml})}" title="Content block HTML preview"></iframe>` : ''}
274
299
  <slot class="html-content" name="html" style="display: none;"></slot>
275
300
  <slot name="text" style="display: none;"></slot>
276
301
  <div class="${classMap({'text-content': true, 'hidden': initialShowHtml})}">
277
302
  ${text.map((section) => html`
278
303
  ${section.type === 'reply' ? html`
279
- <div class="toggle-reply" @click="${this.showReply}">...</div>` : ''}
304
+ <div class="toggle-reply" role="button" tabindex="0" aria-label="Show quoted text"
305
+ @click="${this.showReply}"
306
+ @keydown="${this._handleReplyKeyDown}">...</div>` : ''}
280
307
  <div class=${classMap({
281
308
  'text-section': true,
282
309
  'text-section--reply': section.type === 'reply',
@@ -307,7 +334,7 @@ export default class ContentBlock extends ZincElement {
307
334
  protected truncateText() {
308
335
  const textContent = this.querySelector('[slot="text"]') as HTMLDivElement | null;
309
336
  if (!textContent) return '';
310
- const trimmed = htmlToText(textContent.innerText);
337
+ const trimmed = htmlToText(textContent.textContent ?? '');
311
338
  return trimmed.length > 32 ? trimmed.substring(0, 32) + '...' : trimmed;
312
339
  }
313
340
 
@@ -379,13 +406,15 @@ export default class ContentBlock extends ZincElement {
379
406
  const textContent = this.querySelector('[slot="text"]') as HTMLDivElement | null;
380
407
  const textRows: TextRow[] = [];
381
408
 
382
- if (textContent && looksLikeHtml(textContent.innerText)) {
383
- this._textRows = [{lines: [sanitizeHtml(textContent.innerText, EDITOR_TAGS, true)], type: 'text', html: true}];
409
+ // Not innerText: it forces a layout per read (~6ms each in Safari), and this slot is never rendered.
410
+ const source = textContent?.textContent ?? '';
411
+ if (textContent && looksLikeHtml(source)) {
412
+ this._textRows = [{lines: [sanitizeHtml(source, EDITOR_TAGS, true)], type: 'text', html: true}];
384
413
  return this._textRows;
385
414
  }
386
415
 
387
416
  if (textContent) {
388
- const text = textContent.innerText.replace(/<br\s*\/?>/gi, '\n');
417
+ const text = source.replace(/<br\s*\/?>/gi, '\n');
389
418
  const rows = text.split('\n');
390
419
  let previousType: TextRow['type'] | null = null;
391
420
  let forceReply = false;
@@ -18,6 +18,11 @@
18
18
 
19
19
  .content-block--collapsible .content-block-header {
20
20
  cursor: pointer;
21
+
22
+ &:focus-visible {
23
+ outline: var(--zn-focus-ring);
24
+ border-radius: var(--zn-border-radius-small);
25
+ }
21
26
  }
22
27
 
23
28
  .content-block-header__icon {
@@ -37,6 +42,7 @@
37
42
  }
38
43
 
39
44
  .content-block-header__caption {
45
+ font-family: var(--zn-text-h1-font-family, inherit);
40
46
  font-weight: var(--zn-text-h1-font-weight);
41
47
  font-size: var(--zn-text-h1-font-size);
42
48
  color: rgba(var(--zn-text-panel-title), 100%);
@@ -130,18 +136,18 @@
130
136
  }
131
137
 
132
138
  code {
133
- background-color: #f0f0f0;
139
+ background-color: var(--zn-code-inline-background, #f0f0f0);
134
140
  border-radius: 3px;
135
141
  font-size: 85%;
136
142
  padding: 2px 4px;
137
143
  }
138
144
 
139
145
  pre {
140
- background-color: #23241f;
146
+ background-color: var(--zn-code-background, #23241f);
141
147
  border-radius: 3px;
142
148
  margin-block: 5px;
143
149
  padding: 5px 10px;
144
- color: #f8f8f2;
150
+ color: var(--zn-code-color, #f8f8f2);
145
151
  overflow: auto;
146
152
  }
147
153
 
@@ -176,7 +182,7 @@ li > ol, li > ul {
176
182
  }
177
183
 
178
184
  li[data-list=checked] > .ql-ui, li[data-list=unchecked] > .ql-ui {
179
- color: #777;
185
+ color: var(--zn-content-block-meta-color, #777);
180
186
  }
181
187
 
182
188
  li {
@@ -207,7 +213,7 @@ li[data-list="unchecked"]::before {
207
213
 
208
214
  li[data-list="checked"]::before,
209
215
  li[data-list="unchecked"]::before {
210
- color: #777;
216
+ color: var(--zn-content-block-meta-color, #777);
211
217
  }
212
218
 
213
219
  ol li::before,
@@ -17,6 +17,13 @@ describe('<zn-content-block>', () => {
17
17
  expect(el).to.exist;
18
18
  });
19
19
 
20
+ it('should only create the html preview frame when there is html', async () => {
21
+ const el = await fixture<LitElement>('<zn-content-block><div slot="text">plain</div></zn-content-block>');
22
+ await el.updateComplete;
23
+
24
+ expect(el.shadowRoot!.querySelector('iframe')).to.be.null;
25
+ });
26
+
20
27
  it('should decode escaped source in the html body once', async () => {
21
28
  const el = await fixture<LitElement>(
22
29
  '<zn-content-block><div slot="html">&lt;p&gt;Test&amp;nbsp;Format&lt;/p&gt;</div></zn-content-block>'
@@ -27,6 +34,25 @@ describe('<zn-content-block>', () => {
27
34
  expect(iframe.srcdoc).to.contain('<p>Test&nbsp;Format</p>');
28
35
  });
29
36
 
37
+ it('should read the text slot without forcing layout', async () => {
38
+ const descriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'innerText')!;
39
+ let reads = 0;
40
+ Object.defineProperty(HTMLElement.prototype, 'innerText', {
41
+ ...descriptor,
42
+ get() {
43
+ reads++;
44
+ return descriptor.get!.call(this);
45
+ }
46
+ });
47
+ try {
48
+ const content = await textSection('line one<br>\nline two');
49
+ expect(content.textContent).to.contain('line two');
50
+ } finally {
51
+ Object.defineProperty(HTMLElement.prototype, 'innerText', descriptor);
52
+ }
53
+ expect(reads).to.equal(0);
54
+ });
55
+
30
56
  it('should render plain text in the text body as text', async () => {
31
57
  const content = await textSection('1 &lt; 2 &amp;&amp; 3 &gt; 2');
32
58
 
@@ -44,7 +44,7 @@ export default class ZnCopyButton extends ZincElement {
44
44
 
45
45
  @property() src = '';
46
46
 
47
- @property({type: Number, reflect: true}) size: number = 24;
47
+ @property({type: Number, reflect: true}) size: number = 16;
48
48
 
49
49
  /**
50
50
  * An id that references an element in the same document from which data will be copied. If both this and `value` are
@@ -68,7 +68,7 @@ export default class ZnCopyButton extends ZincElement {
68
68
  content=${copyLabel}>
69
69
  <button class="copy-button__button" part="button" @click=${this.handleCopy}>
70
70
  <slot part="copy-icon" name="copy-icon">
71
- <zn-icon src="${this.src ? this.src : 'content_copy'}" size="${this.size}"></zn-icon>
71
+ <zn-icon src="${this.src ? this.src : 'copy@lu'}" size="${this.size}"></zn-icon>
72
72
  </slot>
73
73
  <slot part="success-icon" name="success-icon" hidden>
74
74
  <zn-icon src="check" size="${this.size}"></zn-icon>