@kubex/zinc 1.1.184 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) 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 +10344 -2583
  6. package/dist/vscode.html-custom-data.json +1102 -125
  7. package/dist/web-types.json +2217 -224
  8. package/dist/zn.d.ts +2306 -417
  9. package/dist/zn.min.css +1 -1
  10. package/dist/zn.min.js +2313 -1635
  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/filter-wrapper.md +20 -0
  33. package/docs/pages/components/icon.md +46 -1
  34. package/docs/pages/components/input.md +30 -11
  35. package/docs/pages/components/item.md +35 -0
  36. package/docs/pages/components/key-value.md +25 -0
  37. package/docs/pages/components/menu.md +74 -7
  38. package/docs/pages/components/nav-item.md +15 -0
  39. package/docs/pages/components/nav-list.md +132 -0
  40. package/docs/pages/components/navbar.md +100 -1
  41. package/docs/pages/components/page.md +242 -74
  42. package/docs/pages/components/priority-list.md +43 -5
  43. package/docs/pages/components/query-builder.md +23 -0
  44. package/docs/pages/components/radio-group.md +33 -1
  45. package/docs/pages/components/radio.md +1 -1
  46. package/docs/pages/components/report-table.md +202 -0
  47. package/docs/pages/components/stat.md +30 -0
  48. package/docs/pages/components/tile.md +11 -0
  49. package/docs/pages/components/tooltip.md +1 -1
  50. package/docs/pages/components/translation-grid.md +86 -0
  51. package/docs/pages/components/vertical-stepper.md +108 -64
  52. package/package.json +2 -1
  53. package/scss/_global-spacing.scss +2 -2
  54. package/scss/_root.scss +11 -171
  55. package/scss/boot.scss +14 -0
  56. package/scss/mixins/_helper-mixins.scss +24 -2
  57. package/scss/mixins/_motion-mixins.scss +126 -0
  58. package/scss/mixins/_spacing-mixins.scss +4 -3
  59. package/scss/mixins/_tab-indicator-mixins.scss +12 -0
  60. package/scss/mixins/_typography-mixins.scss +1 -1
  61. package/scss/mixins/index.scss +14 -0
  62. package/scss/shared/_base.scss +32 -1
  63. package/scss/shared/_button-mixin.scss +7 -5
  64. package/scss/shared/_table.scss +35 -4
  65. package/scss/shared/nav.scss +4 -0
  66. package/scss/shared/shimmer.scss +1 -1
  67. package/scss/table-controls.scss +206 -0
  68. package/scss/themes/_dark.scss +1 -3
  69. package/scss/themes/_index.scss +1 -1
  70. package/scss/themes/_light.scss +46 -6
  71. package/scss/themes/_modes.scss +11 -11
  72. package/scss/themes/_openbyte.scss +944 -0
  73. package/scss/themes/_typography.scss +4 -2
  74. package/scss/variables/index.scss +0 -9
  75. package/src/components/alert/alert.component.ts +14 -4
  76. package/src/components/alert/alert.scss +55 -69
  77. package/src/components/alert/alert.test.ts +8 -0
  78. package/src/components/animated-button/animated-button.component.ts +3 -2
  79. package/src/components/animated-button/animated-button.scss +6 -23
  80. package/src/components/animated-button/animated-button.test.ts +4 -3
  81. package/src/components/avatar-group/avatar-group.component.ts +84 -0
  82. package/src/components/avatar-group/avatar-group.scss +54 -0
  83. package/src/components/avatar-group/avatar-group.test.ts +59 -0
  84. package/src/components/avatar-group/index.ts +12 -0
  85. package/src/components/badge/badge.component.ts +49 -0
  86. package/src/components/badge/badge.scss +80 -0
  87. package/src/components/badge/badge.test.ts +34 -0
  88. package/src/components/badge/index.ts +12 -0
  89. package/src/components/bulk-actions/bulk-actions.component.ts +14 -2
  90. package/src/components/button/button.component.ts +242 -11
  91. package/src/components/button/button.scss +133 -25
  92. package/src/components/button/button.test.ts +122 -0
  93. package/src/components/button-menu/button-menu.component.ts +32 -11
  94. package/src/components/button-menu/button-menu.scss +5 -1
  95. package/src/components/channel-tile/channel-tile.component.ts +34 -27
  96. package/src/components/channel-tile/channel-tile.scss +76 -43
  97. package/src/components/chart/builders.test.ts +46 -0
  98. package/src/components/chart/builders.ts +27 -3
  99. package/src/components/chart/chart-live.test.ts +4 -6
  100. package/src/components/chart/chart.component.ts +125 -5
  101. package/src/components/chart/chart.scss +121 -0
  102. package/src/components/chart/chart.test.ts +81 -0
  103. package/src/components/chat-message/chat-message.component.ts +21 -1
  104. package/src/components/chat-message/chat-message.scss +13 -2
  105. package/src/components/chat-message/chat-message.test.ts +9 -0
  106. package/src/components/checkbox/checkbox.component.ts +61 -27
  107. package/src/components/checkbox/checkbox.scss +58 -25
  108. package/src/components/checkbox-group/checkbox-group.component.ts +7 -1
  109. package/src/components/chip/chip.component.ts +11 -1
  110. package/src/components/chip/chip.scss +91 -26
  111. package/src/components/chip/chip.test.ts +17 -0
  112. package/src/components/collapsible/collapsible.component.ts +17 -3
  113. package/src/components/collapsible/collapsible.scss +19 -10
  114. package/src/components/color-picker/color-picker.component.ts +277 -0
  115. package/src/components/color-picker/color-picker.scss +141 -0
  116. package/src/components/color-picker/color-picker.test.ts +57 -0
  117. package/src/components/color-picker/index.ts +12 -0
  118. package/src/components/cols/cols.component.ts +17 -3
  119. package/src/components/cols/cols.scss +24 -13
  120. package/src/components/cols/cols.test.ts +33 -0
  121. package/src/components/confirm/confirm.component.ts +20 -6
  122. package/src/components/confirm/confirm.test.ts +52 -0
  123. package/src/components/content-block/content-block.component.ts +38 -9
  124. package/src/components/content-block/content-block.scss +11 -5
  125. package/src/components/content-block/content-block.test.ts +26 -0
  126. package/src/components/copy-button/copy-button.component.ts +2 -2
  127. package/src/components/copy-button/copy-button.scss +17 -4
  128. package/src/components/data-select/data-select.component.ts +3 -1
  129. package/src/components/data-table/data-table.component.ts +364 -142
  130. package/src/components/data-table/data-table.scss +133 -60
  131. package/src/components/data-table/data-table.test.ts +356 -4
  132. package/src/components/data-table-filter/data-table-filter.component.ts +426 -406
  133. package/src/components/data-table-filter/data-table-filter.scss +176 -148
  134. package/src/components/data-table-filter/data-table-filter.test.ts +271 -273
  135. package/src/components/data-table-search/data-table-search.component.ts +4 -2
  136. package/src/components/data-table-search/data-table-search.scss +8 -1
  137. package/src/components/data-table-search/data-table-search.test.ts +29 -0
  138. package/src/components/date-range/date-range-math.test.ts +78 -0
  139. package/src/components/date-range/date-range-math.ts +105 -0
  140. package/src/components/date-range/date-range.component.ts +375 -0
  141. package/src/components/date-range/date-range.scss +272 -0
  142. package/src/components/date-range/date-range.test.ts +247 -0
  143. package/src/components/date-range/index.ts +12 -0
  144. package/src/components/datepicker/datepicker.component.ts +44 -7
  145. package/src/components/datepicker/datepicker.scss +9 -0
  146. package/src/components/datepicker/datepicker.test.ts +2 -2
  147. package/src/components/dialog/dialog.component.ts +38 -19
  148. package/src/components/dialog/dialog.scss +65 -36
  149. package/src/components/dialog/dialog.test.ts +14 -0
  150. package/src/components/diff/diff.component.ts +55 -0
  151. package/src/components/diff/diff.scss +46 -0
  152. package/src/components/diff/diff.test.ts +15 -0
  153. package/src/components/diff/index.ts +12 -0
  154. package/src/components/diff-row/diff-row.component.ts +75 -0
  155. package/src/components/diff-row/diff-row.scss +70 -0
  156. package/src/components/diff-row/diff-row.test.ts +37 -0
  157. package/src/components/diff-row/index.ts +12 -0
  158. package/src/components/dropdown/dropdown.component.ts +12 -10
  159. package/src/components/dropdown/dropdown.scss +2 -0
  160. package/src/components/editor/editor.component.ts +159 -11
  161. package/src/components/editor/editor.scss +250 -1
  162. package/src/components/editor/editor.test.ts +31 -3
  163. package/src/components/editor/modules/ai/panel/ai-panel.scss +0 -1
  164. package/src/components/editor/modules/attachment/attachment.ts +53 -31
  165. package/src/components/editor/modules/context-menu/context-menu.ts +17 -0
  166. package/src/components/editor/modules/dialog/dialog.component.ts +23 -1
  167. package/src/components/editor/modules/dialog/dialog.test.ts +28 -0
  168. package/src/components/editor/modules/emoji/emoji.ts +4 -5
  169. package/src/components/editor/modules/merge-field/merge-field.ts +83 -0
  170. package/src/components/editor/modules/toolbar/toolbar.component.ts +121 -68
  171. package/src/components/editor/modules/toolbar/toolbar.scss +38 -0
  172. package/src/components/editor/modules/toolbar/toolbar.ts +25 -1
  173. package/src/components/empty-state/empty-state.component.ts +6 -1
  174. package/src/components/empty-state/empty-state.scss +21 -4
  175. package/src/components/expanding-action/expanding-action.component.ts +22 -34
  176. package/src/components/expanding-action/expanding-action.scss +3 -45
  177. package/src/components/expanding-action/expanding-action.test.ts +2 -1
  178. package/src/components/file/file.component.ts +30 -2
  179. package/src/components/file/file.scss +6 -0
  180. package/src/components/filter-wrapper/filter-wrapper.component.ts +45 -10
  181. package/src/components/filter-wrapper/filter-wrapper.test.ts +58 -2
  182. package/src/components/flow-builder/flow-builder.component.ts +36 -3
  183. package/src/components/flow-builder/flow-builder.scss +0 -6
  184. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.component.ts +8 -0
  185. package/src/components/flow-builder/modules/flow-canvas/flow-canvas.scss +10 -5
  186. package/src/components/flow-builder/modules/flow-node/flow-node.component.ts +17 -0
  187. package/src/components/flow-builder/modules/flow-node/flow-node.scss +10 -0
  188. package/src/components/form-actions/form-actions.component.ts +48 -2
  189. package/src/components/form-actions/form-actions.scss +1 -1
  190. package/src/components/form-group/form-group.component.ts +10 -3
  191. package/src/components/form-group/form-group.scss +37 -4
  192. package/src/components/form-group/form-group.test.ts +10 -0
  193. package/src/components/header/header.component.ts +11 -4
  194. package/src/components/header/header.scss +47 -5
  195. package/src/components/hover-container/hover-container.component.ts +4 -5
  196. package/src/components/icon/icon.component.ts +95 -9
  197. package/src/components/icon/icon.scss +70 -6
  198. package/src/components/icon/icon.test.ts +55 -0
  199. package/src/components/icon-picker/icon-picker.component.ts +35 -1
  200. package/src/components/inline-edit/inline-edit.component.ts +38 -8
  201. package/src/components/inline-edit/inline-edit.scss +128 -19
  202. package/src/components/input/input.component.ts +173 -297
  203. package/src/components/input/input.scss +65 -43
  204. package/src/components/input/input.test.ts +86 -4
  205. package/src/components/item/item.component.ts +12 -0
  206. package/src/components/item/item.scss +102 -3
  207. package/src/components/item/item.test.ts +23 -0
  208. package/src/components/key/key.component.ts +2 -2
  209. package/src/components/key/key.scss +11 -0
  210. package/src/components/key-value/index.ts +12 -0
  211. package/src/components/key-value/key-value.component.ts +160 -0
  212. package/src/components/key-value/key-value.scss +20 -0
  213. package/src/components/key-value/key-value.test.ts +22 -0
  214. package/src/components/markdown-editor/markdown-editor.component.ts +8 -1
  215. package/src/components/menu/menu.component.ts +21 -2
  216. package/src/components/menu/menu.scss +43 -23
  217. package/src/components/menu/menu.test.ts +33 -0
  218. package/src/components/menu-item/menu-item.component.ts +13 -2
  219. package/src/components/menu-item/menu-item.scss +56 -23
  220. package/src/components/menu-item/menu-item.test.ts +31 -0
  221. package/src/components/menu-item/submenu-controller.ts +25 -15
  222. package/src/components/menu-label/index.ts +12 -0
  223. package/src/components/menu-label/menu-label.component.ts +30 -0
  224. package/src/components/menu-label/menu-label.scss +18 -0
  225. package/src/components/nav-item/index.ts +12 -0
  226. package/src/components/nav-item/nav-item.component.ts +83 -0
  227. package/src/components/nav-item/nav-item.scss +128 -0
  228. package/src/components/nav-list/index.ts +12 -0
  229. package/src/components/nav-list/nav-list.component.ts +313 -0
  230. package/src/components/nav-list/nav-list.scss +87 -0
  231. package/src/components/nav-list/nav-list.test.ts +250 -0
  232. package/src/components/navbar/navbar.component.ts +235 -171
  233. package/src/components/navbar/navbar.scss +333 -169
  234. package/src/components/navbar/navbar.test.ts +63 -143
  235. package/src/components/page/page.component.ts +114 -29
  236. package/src/components/page/page.scss +223 -95
  237. package/src/components/page/page.test.ts +214 -3
  238. package/src/components/page-builder/page-builder.component.ts +51 -5
  239. package/src/components/page-builder/page-builder.scss +6 -1
  240. package/src/components/page-nav/page-nav.component.ts +25 -3
  241. package/src/components/page-nav/page-nav.scss +10 -2
  242. package/src/components/pagination/pagination.scss +1 -1
  243. package/src/components/panel/panel.component.ts +14 -13
  244. package/src/components/panel/panel.scss +14 -10
  245. package/src/components/panel/panel.test.ts +42 -0
  246. package/src/components/popup/popup.component.ts +20 -13
  247. package/src/components/popup/popup.test.ts +21 -1
  248. package/src/components/priority-list/priority-list.component.ts +157 -172
  249. package/src/components/priority-list/priority-list.scss +113 -17
  250. package/src/components/priority-list/priority-list.test.ts +301 -3
  251. package/src/components/progress-bar/progress-bar.component.ts +1 -1
  252. package/src/components/progress-bar/progress-bar.scss +16 -4
  253. package/src/components/progress-tile/progress-tile.scss +1 -1
  254. package/src/components/query-builder/query-builder.component.ts +85 -10
  255. package/src/components/query-builder/query-builder.scss +7 -1
  256. package/src/components/query-builder/query-builder.test.ts +40 -0
  257. package/src/components/radio/radio.component.ts +57 -18
  258. package/src/components/radio/radio.scss +101 -26
  259. package/src/components/radio-group/radio-group.component.ts +45 -7
  260. package/src/components/radio-group/radio-group.scss +17 -0
  261. package/src/components/radio-group/radio-group.test.ts +63 -2
  262. package/src/components/rating/rating.component.ts +23 -0
  263. package/src/components/rating/rating.scss +1 -1
  264. package/src/components/remarkd-editor/remarkd-editor.component.ts +60 -5
  265. package/src/components/remarkd-editor/remarkd-editor.scss +12 -4
  266. package/src/components/report-table/index.ts +12 -0
  267. package/src/components/report-table/report-format.test.ts +86 -0
  268. package/src/components/report-table/report-format.ts +72 -0
  269. package/src/components/report-table/report-math.test.ts +74 -0
  270. package/src/components/report-table/report-math.ts +252 -0
  271. package/src/components/report-table/report-table.component.ts +681 -0
  272. package/src/components/report-table/report-table.scss +328 -0
  273. package/src/components/report-table/report-table.test.ts +702 -0
  274. package/src/components/reveal/reveal.component.ts +15 -1
  275. package/src/components/reveal/reveal.scss +5 -0
  276. package/src/components/schedule-builder/schedule-builder.component.ts +23 -8
  277. package/src/components/scroll-container/scroll-container.component.ts +19 -1
  278. package/src/components/scroll-container/scroll-container.scss +6 -1
  279. package/src/components/select/select.component.ts +52 -36
  280. package/src/components/select/select.scss +42 -25
  281. package/src/components/select/select.test.ts +14 -2
  282. package/src/components/settings-container/settings-container.scss +18 -5
  283. package/src/components/sidebar/sidebar.component.ts +8 -1
  284. package/src/components/sidebar/sidebar.scss +6 -1
  285. package/src/components/skeleton/skeleton.component.ts +3 -3
  286. package/src/components/skeleton/skeleton.scss +6 -6
  287. package/src/components/skeleton/skeleton.test.ts +9 -0
  288. package/src/components/slash-menu/slash-menu.scss +1 -1
  289. package/src/components/slideout/slideout.component.ts +20 -3
  290. package/src/components/slideout/slideout.scss +13 -6
  291. package/src/components/slideout/slideout.test.ts +19 -0
  292. package/src/components/split-button/split-button.component.ts +1 -1
  293. package/src/components/split-pane/split-pane.component.ts +71 -8
  294. package/src/components/split-pane/split-pane.scss +145 -41
  295. package/src/components/split-pane/split-pane.test.ts +23 -3
  296. package/src/components/stat/stat.component.ts +209 -14
  297. package/src/components/stat/stat.scss +305 -5
  298. package/src/components/stat/stat.test.ts +143 -2
  299. package/src/components/status-indicator/status-indicator.scss +22 -21
  300. package/src/components/stepper/stepper.scss +3 -3
  301. package/src/components/tab/tab.component.ts +1 -0
  302. package/src/components/table/table.component.ts +12 -1
  303. package/src/components/table/table.scss +21 -13
  304. package/src/components/table/table.test.ts +17 -0
  305. package/src/components/tabs/tabs.component.ts +150 -37
  306. package/src/components/tabs/tabs.scss +48 -7
  307. package/src/components/tabs/tabs.test.ts +169 -0
  308. package/src/components/textarea/textarea.component.ts +25 -3
  309. package/src/components/textarea/textarea.scss +10 -0
  310. package/src/components/textarea/textarea.test.ts +8 -4
  311. package/src/components/theme-editor/theme-editor.scss +0 -6
  312. package/src/components/tile/tile.component.ts +32 -2
  313. package/src/components/tile/tile.scss +40 -7
  314. package/src/components/tile/tile.test.ts +10 -0
  315. package/src/components/toggle/toggle.component.ts +23 -7
  316. package/src/components/toggle/toggle.scss +36 -29
  317. package/src/components/toggle/toggle.test.ts +17 -0
  318. package/src/components/tooltip/tooltip.component.ts +3 -0
  319. package/src/components/tooltip/tooltip.scss +11 -6
  320. package/src/components/tooltip/tooltip.test.ts +12 -0
  321. package/src/components/translation-field/index.ts +12 -0
  322. package/src/components/translation-field/translation-field.component.ts +55 -0
  323. package/src/components/translation-field/translation-field.scss +101 -0
  324. package/src/components/translation-fields/index.ts +12 -0
  325. package/src/components/translation-fields/translation-fields.component.ts +80 -0
  326. package/src/components/translation-fields/translation-fields.scss +60 -0
  327. package/src/components/translation-grid/index.ts +12 -0
  328. package/src/components/translation-grid/translation-grid.component.ts +157 -0
  329. package/src/components/translation-grid/translation-grid.scss +138 -0
  330. package/src/components/translation-grid/translation-grid.test.ts +28 -0
  331. package/src/components/vertical-stepper/vertical-stepper.component.ts +35 -9
  332. package/src/components/vertical-stepper/vertical-stepper.scss +110 -39
  333. package/src/components/vertical-stepper/vertical-stepper.test.ts +35 -0
  334. package/src/components/well/well.scss +2 -2
  335. package/src/events/events.ts +2 -0
  336. package/src/events/zn-chart-click.ts +13 -0
  337. package/src/events/zn-report-change.ts +7 -0
  338. package/src/form-control.scss +36 -3
  339. package/src/internal/anchored-popover.ts +175 -0
  340. package/src/internal/animate.ts +19 -5
  341. package/src/internal/cosmic-border.ts +15 -0
  342. package/src/internal/form.ts +1 -1
  343. package/src/internal/hover-intent.ts +15 -0
  344. package/src/internal/input-modality.ts +15 -0
  345. package/src/internal/pointer-intent.ts +37 -0
  346. package/src/internal/reorder.ts +625 -0
  347. package/src/internal/scroll.ts +51 -3
  348. package/src/internal/selection-card.ts +1 -1
  349. package/src/internal/tab-indicator.ts +92 -0
  350. package/src/internal/table-sort.ts +25 -0
  351. package/src/internal/table-tabs.ts +108 -0
  352. package/src/internal/test-drag.ts +35 -0
  353. package/src/internal/theme-openbyte.test.ts +126 -0
  354. package/src/internal/theme.ts +4 -4
  355. package/src/internal/zinc-element.ts +2 -2
  356. package/src/selection-card.scss +25 -0
  357. package/src/types/web-test-runner-commands.d.ts +1 -0
  358. package/src/utilities/color.test.ts +43 -0
  359. package/src/utilities/color.ts +189 -0
  360. package/src/zinc.ts +14 -0
  361. package/.github/workflows/eleventy_build.yml +0 -42
  362. package/scss/themes/_aura.scss +0 -114
@@ -60,6 +60,7 @@ export default class ZnIconPicker extends ZincElement implements ZincFormControl
60
60
  @state() private _searchQuery = '';
61
61
  @state() private _iconList: string[] = [];
62
62
  @state() private _filteredIcons: string[] = [];
63
+ @state() private _gridFocusIcon = '';
63
64
 
64
65
  // Pending selections (not committed until confirm)
65
66
  @state() private _pendingIcon = '';
@@ -280,6 +281,35 @@ export default class ZnIconPicker extends ZincElement implements ZincFormControl
280
281
 
281
282
  private handleIconSelect(iconName: string) {
282
283
  this._pendingIcon = iconName;
284
+ this._gridFocusIcon = iconName;
285
+ }
286
+
287
+ private _gridTabStop() {
288
+ if (this._filteredIcons.includes(this._gridFocusIcon)) return this._gridFocusIcon;
289
+ if (this._filteredIcons.includes(this._pendingIcon)) return this._pendingIcon;
290
+ return this._filteredIcons[0];
291
+ }
292
+
293
+ private _handleGridKeyDown(e: KeyboardEvent) {
294
+ const items = [...(e.currentTarget as HTMLElement).querySelectorAll<HTMLButtonElement>('.icon-picker__grid-item')];
295
+ const index = items.indexOf(e.target as HTMLButtonElement);
296
+ if (index === -1) return;
297
+
298
+ const columns = Math.max(1, items.filter(item => item.offsetTop === items[0].offsetTop).length);
299
+ let next: number;
300
+ switch (e.key) {
301
+ case 'ArrowRight': next = index + 1; break;
302
+ case 'ArrowLeft': next = index - 1; break;
303
+ case 'ArrowDown': next = index + columns; break;
304
+ case 'ArrowUp': next = index - columns; break;
305
+ case 'Home': next = 0; break;
306
+ case 'End': next = items.length - 1; break;
307
+ default: return;
308
+ }
309
+ e.preventDefault();
310
+ next = Math.max(0, Math.min(items.length - 1, next));
311
+ this._gridFocusIcon = this._filteredIcons[next];
312
+ items[next].focus();
283
313
  }
284
314
 
285
315
  private async handleLibraryChange(e: Event) {
@@ -326,6 +356,7 @@ export default class ZnIconPicker extends ZincElement implements ZincFormControl
326
356
  }
327
357
 
328
358
  private _handleTriggerKeyDown(e: KeyboardEvent) {
359
+ if (e.target !== e.currentTarget) return;
329
360
  if (e.key === 'Enter' || e.key === ' ') {
330
361
  e.preventDefault();
331
362
  this._handleTriggerClick();
@@ -340,6 +371,7 @@ export default class ZnIconPicker extends ZincElement implements ZincFormControl
340
371
  // auto-detection renders an <img> instead of a font ligature.
341
372
  const triggerIcon = this._fileUrl ?? this.icon;
342
373
  const triggerLibrary = hasValue && !this.isImageValue ? this.library : nothing;
374
+ const gridTabStop = this._gridTabStop();
343
375
  const pendingPreviewUrl = this._pendingFileUrl ?? (this.isImageValue && !this._file ? this.icon : this._fileUrl);
344
376
 
345
377
  return html`
@@ -503,7 +535,7 @@ export default class ZnIconPicker extends ZincElement implements ZincFormControl
503
535
  <zn-icon slot="prefix" src="search" size="18"></zn-icon>
504
536
  </zn-input>
505
537
 
506
- <div class="icon-picker__grid">
538
+ <div class="icon-picker__grid" @keydown=${this._handleGridKeyDown}>
507
539
  ${this._filteredIcons.length === 0 ? html`
508
540
  <div class="icon-picker__no-results">No icons found</div>
509
541
  ` : this._filteredIcons.map(iconName => html`
@@ -514,6 +546,8 @@ export default class ZnIconPicker extends ZincElement implements ZincFormControl
514
546
  'icon-picker__grid-item--selected': iconName === this._pendingIcon
515
547
  })}
516
548
  title=${iconName}
549
+ aria-pressed=${iconName === this._pendingIcon ? 'true' : 'false'}
550
+ tabindex=${iconName === gridTabStop ? '0' : '-1'}
517
551
  @click=${() => this.handleIconSelect(iconName)}>
518
552
  <zn-icon
519
553
  src=${iconName}
@@ -32,7 +32,9 @@ import styles from './inline-edit.scss';
32
32
  *
33
33
  * @csspart base - The component's base wrapper.
34
34
  *
35
- * @cssproperty --example - An example CSS custom property.
35
+ * @cssproperty --zn-inline-edit-hover-background - The fill behind a field while hovered or focused.
36
+ * @cssproperty --zn-inline-edit-bleed - How far the hover fill extends past the left edge of the value.
37
+ * @cssproperty --zn-inline-edit-underline-color - The dotted underline marking an editable value at rest.
36
38
  */
37
39
  export default class ZnInlineEdit extends ZincElement implements ZincFormControl {
38
40
  static styles: CSSResultGroup = [unsafeCSS(formElementStyles), unsafeCSS(styles)];
@@ -181,6 +183,8 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
181
183
 
182
184
  @state() private isEditing: boolean;
183
185
 
186
+ @state() private textScrolledToEnd = false;
187
+
184
188
  private _valueBeforeEdit: string | string[];
185
189
  private _editStartValue: string | string[];
186
190
 
@@ -258,9 +262,24 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
258
262
  if (this.input instanceof ZnSelect && !this.isEditing) {
259
263
  await this.input.hide();
260
264
  }
265
+ if (this.isEditing) {
266
+ this.textControl?.addEventListener('scroll', this.updateTextScrolledToEnd);
267
+ this.updateTextScrolledToEnd();
268
+ }
261
269
  this.conditionalController.check();
262
270
  }
263
271
 
272
+ private get textControl(): HTMLInputElement | HTMLTextAreaElement | undefined {
273
+ const control: unknown = (this.input as Partial<ZnInput> | undefined)?.input;
274
+ return control instanceof HTMLInputElement || control instanceof HTMLTextAreaElement ? control : undefined;
275
+ }
276
+
277
+ // The fade under the actions signals text continuing beneath them, so it goes once the end is in view
278
+ updateTextScrolledToEnd = () => {
279
+ const control = this.textControl;
280
+ this.textScrolledToEnd = !!control && control.scrollLeft + control.clientWidth >= control.scrollWidth - 1;
281
+ };
282
+
264
283
  mouseEventHandler = (e: MouseEvent) => {
265
284
  if (this.isEditing && !this.contains(e.target as Node)) {
266
285
  const hasChanged = Array.isArray(this.value)
@@ -339,12 +358,20 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
339
358
  };
340
359
 
341
360
  handleInput = (e: Event) => {
342
- if (this.disabled || !this.isEditing) {
361
+ if (this.disabled) {
343
362
  return;
344
363
  }
345
364
 
365
+ // Keyboard users tab straight into the field, so typing starts an edit as a click would
366
+ if (!this.isEditing) {
367
+ this._valueBeforeEdit = this.value;
368
+ this._editStartValue = this.value;
369
+ this.isEditing = true;
370
+ }
371
+
346
372
  this.value = (e.target as (HTMLInputElement | HTMLSelectElement)).value;
347
373
  this.emit('zn-input');
374
+ requestAnimationFrame(this.updateTextScrolledToEnd);
348
375
  };
349
376
 
350
377
  private moveSlottedOptionsToSelect() {
@@ -405,6 +432,7 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
405
432
  <div class="${classMap({
406
433
  'ai': true,
407
434
  'ai--editing': this.isEditing,
435
+ 'ai--text-end': this.textScrolledToEnd,
408
436
  'ai--focused': this.hasFocus,
409
437
  'ai--disabled': this.disabled,
410
438
  'ai--inline': this.inline,
@@ -432,13 +460,15 @@ export default class ZnInlineEdit extends ZincElement implements ZincFormControl
432
460
  <zn-button @click="${this.disabled ? undefined : this.handleEditClick}"
433
461
  class="button--edit"
434
462
  icon="edit"
435
- icon-size="20"
436
- color="secondary"></zn-button>`}` :
463
+ icon-size="16"
464
+ color="transparent"
465
+ icon-button="small"
466
+ plain></zn-button>`}` :
437
467
  html`
438
- <zn-button type="submit" @click="${this.handleSubmitClick}" icon="check" icon-size="20"
439
- color="secondary"></zn-button>
440
- <zn-button type="button" @click="${this.handleCancelClick}" icon="close" icon-size="20"
441
- color="secondary"></zn-button>`}
468
+ <zn-button type="submit" class="button--save" @click="${this.handleSubmitClick}" icon="check"
469
+ icon-size="16" color="transparent" icon-button="small" plain label="Save"></zn-button>
470
+ <zn-button type="button" class="button--cancel" @click="${this.handleCancelClick}" icon="close"
471
+ icon-size="16" color="transparent" icon-button="small" plain label="Cancel"></zn-button>`}
442
472
  </div>
443
473
  </div>
444
474
 
@@ -7,10 +7,45 @@
7
7
  }
8
8
 
9
9
  .ai {
10
+ --bleed: var(--zn-inline-edit-bleed, 10px);
10
11
  display: flex;
11
12
  width: 100%;
12
13
  flex-direction: row;
13
14
  gap: 10px;
15
+ border-radius: var(--zn-border-radius-medium);
16
+ transition: background-color var(--zn-transition-fast) ease;
17
+
18
+ // The hover fill hangs out past the value's left edge, so the text stays aligned with the column
19
+ &:not(.ai--padded) {
20
+ box-sizing: border-box;
21
+ width: calc(100% + var(--bleed));
22
+ margin-inline-start: calc(-1 * var(--bleed));
23
+ padding-inline-start: var(--bleed);
24
+ }
25
+
26
+ // The input's own padding takes over from the bleed, keeping its text roughly where the value was
27
+ &--editing:not(.ai--padded) {
28
+ padding-inline-start: 0;
29
+ }
30
+
31
+ &:not(.ai--editing):not(.ai--disabled) {
32
+ --underline-color: var(--zn-inline-edit-underline-color, var(--zn-color-neutral-300));
33
+
34
+ // Marks the value as editable at rest, without hovering
35
+ .ai__input::part(input),
36
+ .ai__input::part(display-input),
37
+ .ai__reveal::part(base) {
38
+ text-decoration: underline dotted var(--underline-color);
39
+ text-decoration-thickness: 1.5px;
40
+ text-underline-offset: 4px;
41
+ transition: text-decoration-color var(--zn-transition-fast) ease;
42
+ }
43
+
44
+ &:is(:hover, :focus-within) {
45
+ --underline-color: rgb(var(--zn-primary));
46
+ background-color: var(--zn-inline-edit-hover-background, var(--zn-color-primary-50));
47
+ }
48
+ }
14
49
 
15
50
  &:not(.ai--editing) {
16
51
  .ai__input::part(base), .ai__input::part(combobox), .ai__input::part(textarea) {
@@ -32,16 +67,11 @@
32
67
  .ai__input::part(input), .ai__input::part(combobox), .ai__input::part(textarea) {
33
68
  padding: 0;
34
69
  color: rgb(var(--zn-text));
35
- text-decoration: underline;
36
- text-decoration-style: dashed;
37
- text-decoration-color: rgb(var(--zn-primary), 0.5);
38
- text-underline-offset: 3px;
39
70
  }
40
71
 
41
72
  .ai__input::part(textarea) {
42
73
  padding-top: 8px;
43
74
  box-shadow: none;
44
- text-decoration:none;
45
75
  }
46
76
 
47
77
  .ai__input::part(expand-icon) {
@@ -52,8 +82,9 @@
52
82
  display: none;
53
83
  }
54
84
 
55
- &:hover .button--edit {
56
- display: inline-block;
85
+ &:hover .button--edit,
86
+ &:focus-within .button--edit {
87
+ opacity: 1;
57
88
  }
58
89
  }
59
90
 
@@ -117,8 +148,78 @@
117
148
  }
118
149
 
119
150
  &--editing {
151
+ --action-size: 28px;
152
+ --action-inset: 4px;
153
+ --action-room: calc(var(--action-size) * 2 + 2px + var(--action-inset) * 2);
154
+ --fade-floor: rgb(0 0 0 / 0.25);
155
+ position: relative;
156
+
157
+ // Save and cancel sit inside the field's right end, so the row never grows or clips
120
158
  .ai__right {
121
159
  display: flex !important;
160
+ position: absolute;
161
+ inset-block-start: 0;
162
+ inset-inline-end: var(--action-inset);
163
+ height: var(--zn-input-height-medium);
164
+ gap: 2px;
165
+ }
166
+
167
+ .ai__input::part(input),
168
+ .ai__input::part(combobox),
169
+ .ai__input::part(textarea) {
170
+ // Matches the resting bleed so the text doesn't shift when editing starts
171
+ padding-inline-start: var(--bleed);
172
+ padding-inline-end: var(--action-room);
173
+ text-overflow: clip;
174
+ }
175
+
176
+ // Fades overflowing text toward the actions so it reads as continuing beneath them. Stops short of fully
177
+ // transparent: a caret at the end of overflowing text sits right at the fade's edge.
178
+ .ai__input::part(input),
179
+ .ai__input::part(textarea) {
180
+ mask-image: linear-gradient(to left, var(--fade-floor) var(--action-room), #000 calc(var(--action-room) + 24px));
181
+ }
182
+
183
+ &.ai--text-end .ai__input::part(input),
184
+ &.ai--text-end .ai__input::part(textarea) {
185
+ mask-image: none;
186
+ }
187
+
188
+ // A select's combobox part is the bordered box itself, so only its text is faded
189
+ .ai__input::part(display-input) {
190
+ text-overflow: clip;
191
+ mask-image: linear-gradient(to left, var(--fade-floor), #000 24px);
192
+ }
193
+
194
+ .ai__right zn-button {
195
+ --zn-button-height: var(--action-size);
196
+ --zn-button-icon-width: var(--action-size);
197
+ // Same duration and curve as the input's border, so the edit state arrives as one change
198
+ transition: opacity var(--zn-transition-fast) ease, color var(--zn-transition-fast) ease;
199
+
200
+ @starting-style {
201
+ opacity: 0;
202
+ }
203
+ }
204
+
205
+ .button--save {
206
+ color: rgb(var(--zn-primary));
207
+
208
+ &::part(base) {
209
+ background-color: var(--zn-color-primary-100);
210
+ }
211
+ }
212
+
213
+ .button--cancel {
214
+ color: rgb(var(--zn-color-muted-text, var(--zn-text)));
215
+
216
+ &:hover {
217
+ color: var(--zn-menu-item-danger-hover-color, rgb(var(--zn-color-error)));
218
+
219
+ &::part(base) {
220
+ background-color: var(--zn-menu-item-danger-hover-background, rgba(var(--zn-color-error), 0.1));
221
+ }
222
+ }
122
223
  }
123
224
  }
124
225
 
@@ -143,10 +244,6 @@
143
244
  // Fill the row so hovering anywhere over the field reveals the value
144
245
  &::part(base) {
145
246
  width: 100%;
146
- text-decoration: underline;
147
- text-decoration-style: dashed;
148
- text-decoration-color: rgb(var(--zn-primary), 0.5);
149
- text-underline-offset: 3px;
150
247
  }
151
248
  }
152
249
 
@@ -165,30 +262,42 @@
165
262
 
166
263
  &__right {
167
264
  font-size: 12px;
168
- color: rgb(var(--zn-primary));
265
+ color: var(--zn-color-primary-fg, rgb(var(--zn-primary)));
169
266
  font-weight: 500;
170
267
  cursor: pointer;
171
268
  flex-direction: row;
172
- gap: 10px;
269
+ gap: 6px;
173
270
  align-items: center;
174
271
  justify-content: flex-end;
175
272
 
273
+ zn-button {
274
+ --zn-border-radius: var(--zn-border-radius-medium);
275
+ }
276
+
277
+ // Transparent rather than removed, so hover doesn't reflow the row and keyboard users can still tab to it
176
278
  .button--edit {
177
- display: none;
279
+ opacity: 0;
280
+ color: rgb(var(--zn-primary));
281
+ transition: opacity var(--zn-transition-fast) ease;
282
+
283
+ // Remounts when an edit ends; without this a still-hovered row snaps the pencil back in
284
+ @starting-style {
285
+ opacity: 0;
286
+ }
287
+
288
+ // The field's hover fill already covers it
289
+ &::part(base) {
290
+ background-color: transparent;
291
+ }
178
292
  }
179
293
  }
180
294
 
181
295
  &--disabled:not(.ai--editing) {
182
296
  .ai__input::part(input), .ai__input::part(combobox), .ai__input::part(textarea) {
183
- text-decoration: none;
184
297
  caret-color: transparent;
185
298
  border-radius: 0;
186
299
  }
187
300
 
188
- .ai__reveal::part(base) {
189
- text-decoration: none;
190
- }
191
-
192
301
  .ai__input::part(display-input) {
193
302
  cursor: text;
194
303
  }