@tylertech/forge 3.10.5 → 3.12.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 (257) hide show
  1. package/custom-elements.json +594 -226
  2. package/dist/app-bar/forge-app-bar.css +13 -5
  3. package/dist/button/forge-button.css +14 -6
  4. package/dist/checkbox/forge-checkbox.css +23 -17
  5. package/dist/chips/forge-chips.css +12 -4
  6. package/dist/field/forge-field.css +7 -5
  7. package/dist/floating-action-button/forge-floating-action-button.css +12 -6
  8. package/dist/forge.css +6 -1
  9. package/dist/icon-button/forge-icon-button.css +12 -4
  10. package/dist/lib.js +22 -22
  11. package/dist/lib.js.map +4 -4
  12. package/dist/list/forge-list.css +59 -3
  13. package/dist/radio/forge-radio.css +22 -12
  14. package/dist/skip-link/forge-skip-link.css +38 -32
  15. package/dist/state-layer/forge-state-layer.css +2 -0
  16. package/dist/switch/forge-switch.css +9 -5
  17. package/dist/table/forge-table.css +6 -1
  18. package/dist/vscode.html-custom-data.json +104 -79
  19. package/esm/accordion/accordion.d.ts +2 -0
  20. package/esm/accordion/accordion.js +2 -0
  21. package/esm/app-bar/app-bar/app-bar-adapter.js +2 -2
  22. package/esm/app-bar/app-bar/app-bar.d.ts +1 -1
  23. package/esm/app-bar/app-bar/app-bar.js +1 -1
  24. package/esm/app-bar/help-button/app-bar-help-button.d.ts +1 -1
  25. package/esm/app-bar/help-button/app-bar-help-button.js +1 -1
  26. package/esm/app-bar/menu-button/app-bar-menu-button.d.ts +1 -1
  27. package/esm/app-bar/menu-button/app-bar-menu-button.js +1 -1
  28. package/esm/app-bar/notification-button/app-bar-notification-button.d.ts +2 -0
  29. package/esm/app-bar/notification-button/app-bar-notification-button.js +2 -0
  30. package/esm/app-bar/profile-button/app-bar-profile-button-adapter.d.ts +2 -1
  31. package/esm/app-bar/profile-button/app-bar-profile-button-adapter.js +2 -0
  32. package/esm/app-bar/profile-button/app-bar-profile-button.d.ts +2 -0
  33. package/esm/app-bar/profile-button/app-bar-profile-button.js +2 -0
  34. package/esm/app-bar/search/app-bar-search.d.ts +2 -0
  35. package/esm/app-bar/search/app-bar-search.js +2 -0
  36. package/esm/autocomplete/autocomplete-core.js +16 -3
  37. package/esm/autocomplete/autocomplete.d.ts +2 -0
  38. package/esm/autocomplete/autocomplete.js +2 -0
  39. package/esm/avatar/avatar.d.ts +1 -1
  40. package/esm/avatar/avatar.js +1 -1
  41. package/esm/backdrop/backdrop.d.ts +2 -0
  42. package/esm/backdrop/backdrop.js +2 -0
  43. package/esm/badge/badge.d.ts +2 -0
  44. package/esm/badge/badge.js +2 -0
  45. package/esm/banner/banner.d.ts +1 -1
  46. package/esm/banner/banner.js +1 -1
  47. package/esm/button/base/base-button-adapter.js +2 -2
  48. package/esm/button/button.d.ts +1 -6
  49. package/esm/button/button.js +1 -6
  50. package/esm/button-area/button-area-adapter.js +2 -2
  51. package/esm/button-area/button-area.d.ts +1 -4
  52. package/esm/button-area/button-area.js +1 -4
  53. package/esm/button-toggle/button-toggle/button-toggle-adapter.js +2 -2
  54. package/esm/button-toggle/button-toggle/button-toggle.d.ts +2 -0
  55. package/esm/button-toggle/button-toggle/button-toggle.js +2 -0
  56. package/esm/button-toggle/button-toggle-group/button-toggle-group.d.ts +1 -1
  57. package/esm/button-toggle/button-toggle-group/button-toggle-group.js +1 -1
  58. package/esm/calendar/calendar-menu/calendar-menu.js +1 -1
  59. package/esm/calendar/calendar.d.ts +2 -0
  60. package/esm/calendar/calendar.js +3 -1
  61. package/esm/card/card.d.ts +2 -0
  62. package/esm/card/card.js +2 -0
  63. package/esm/chip-field/chip-field.d.ts +2 -0
  64. package/esm/chip-field/chip-field.js +2 -0
  65. package/esm/chips/chip/chip-adapter.d.ts +3 -0
  66. package/esm/chips/chip/chip-adapter.js +14 -4
  67. package/esm/chips/chip/chip-constants.d.ts +2 -0
  68. package/esm/chips/chip/chip-constants.js +2 -1
  69. package/esm/chips/chip/chip-core.d.ts +4 -0
  70. package/esm/chips/chip/chip-core.js +9 -0
  71. package/esm/chips/chip/chip.d.ts +6 -0
  72. package/esm/chips/chip/chip.js +10 -0
  73. package/esm/chips/chip-set/chip-set.d.ts +1 -1
  74. package/esm/chips/chip-set/chip-set.js +1 -1
  75. package/esm/circular-progress/circular-progress.d.ts +1 -2
  76. package/esm/circular-progress/circular-progress.js +1 -2
  77. package/esm/color-picker/color-picker.d.ts +2 -0
  78. package/esm/color-picker/color-picker.js +3 -1
  79. package/esm/core/utils/a11y-utils.js +17 -0
  80. package/esm/core/utils/utils.js +8 -2
  81. package/esm/date-picker/date-picker.d.ts +2 -0
  82. package/esm/date-picker/date-picker.js +2 -0
  83. package/esm/date-range-picker/date-range-picker.d.ts +2 -0
  84. package/esm/date-range-picker/date-range-picker.js +2 -0
  85. package/esm/deprecated/button/deprecated-button.js +3 -3
  86. package/esm/deprecated/icon-button/deprecated-icon-button.js +2 -2
  87. package/esm/dialog/dialog.d.ts +1 -1
  88. package/esm/dialog/dialog.js +1 -1
  89. package/esm/divider/divider.d.ts +1 -1
  90. package/esm/divider/divider.js +1 -1
  91. package/esm/drawer/base/base-drawer-adapter.d.ts +2 -0
  92. package/esm/drawer/base/base-drawer-adapter.js +3 -0
  93. package/esm/drawer/base/base-drawer-core.js +3 -0
  94. package/esm/drawer/drawer/drawer.d.ts +2 -0
  95. package/esm/drawer/drawer/drawer.js +3 -1
  96. package/esm/drawer/mini-drawer/mini-drawer.d.ts +2 -0
  97. package/esm/drawer/mini-drawer/mini-drawer.js +3 -1
  98. package/esm/drawer/modal-drawer/modal-drawer.d.ts +2 -0
  99. package/esm/drawer/modal-drawer/modal-drawer.js +3 -1
  100. package/esm/expansion-panel/expansion-panel.d.ts +1 -1
  101. package/esm/expansion-panel/expansion-panel.js +1 -1
  102. package/esm/field/field-adapter.js +2 -2
  103. package/esm/field/field-core.d.ts +3 -3
  104. package/esm/field/field.d.ts +1 -2
  105. package/esm/field/field.js +1 -2
  106. package/esm/file-picker/file-picker.d.ts +2 -3
  107. package/esm/file-picker/file-picker.js +2 -3
  108. package/esm/floating-action-button/floating-action-button.d.ts +1 -1
  109. package/esm/floating-action-button/floating-action-button.js +1 -1
  110. package/esm/focus-indicator/focus-indicator-constants.d.ts +1 -11
  111. package/esm/focus-indicator/focus-indicator-constants.js +2 -17
  112. package/esm/focus-indicator/focus-indicator.d.ts +53 -26
  113. package/esm/focus-indicator/focus-indicator.js +139 -62
  114. package/esm/focus-indicator/index.d.ts +0 -2
  115. package/esm/focus-indicator/index.js +0 -2
  116. package/esm/icon/icon.d.ts +1 -1
  117. package/esm/icon/icon.js +1 -1
  118. package/esm/icon-button/icon-button.d.ts +2 -0
  119. package/esm/icon-button/icon-button.js +2 -0
  120. package/esm/inline-message/inline-message.d.ts +1 -1
  121. package/esm/inline-message/inline-message.js +1 -1
  122. package/esm/keyboard-shortcut/keyboard-shortcut.d.ts +2 -0
  123. package/esm/keyboard-shortcut/keyboard-shortcut.js +2 -0
  124. package/esm/label/label.d.ts +1 -1
  125. package/esm/label/label.js +1 -1
  126. package/esm/label-value/label-value.d.ts +1 -1
  127. package/esm/label-value/label-value.js +1 -1
  128. package/esm/linear-progress/linear-progress.d.ts +1 -2
  129. package/esm/linear-progress/linear-progress.js +1 -2
  130. package/esm/list/list/list.d.ts +1 -1
  131. package/esm/list/list/list.js +2 -2
  132. package/esm/list/list-item/list-item-constants.js +1 -1
  133. package/esm/list/list-item/list-item-core.d.ts +2 -0
  134. package/esm/list/list-item/list-item-core.js +29 -6
  135. package/esm/list/list-item/list-item.d.ts +1 -0
  136. package/esm/list/list-item/list-item.js +2 -1
  137. package/esm/list-dropdown/list-dropdown-constants.d.ts +11 -1
  138. package/esm/list-dropdown/list-dropdown-constants.js +6 -1
  139. package/esm/list-dropdown/list-dropdown-utils.d.ts +3 -1
  140. package/esm/list-dropdown/list-dropdown-utils.js +69 -21
  141. package/esm/menu/menu-adapter.d.ts +2 -0
  142. package/esm/menu/menu-adapter.js +12 -8
  143. package/esm/menu/menu-constants.d.ts +1 -0
  144. package/esm/menu/menu-constants.js +3 -2
  145. package/esm/menu/menu-core.d.ts +5 -0
  146. package/esm/menu/menu-core.js +41 -2
  147. package/esm/menu/menu.d.ts +17 -0
  148. package/esm/menu/menu.js +15 -1
  149. package/esm/open-icon/open-icon.d.ts +2 -1
  150. package/esm/open-icon/open-icon.js +2 -1
  151. package/esm/overlay/overlay.d.ts +1 -2
  152. package/esm/overlay/overlay.js +1 -2
  153. package/esm/page-state/page-state.d.ts +2 -1
  154. package/esm/page-state/page-state.js +2 -1
  155. package/esm/paginator/paginator-core.d.ts +16 -0
  156. package/esm/paginator/paginator-core.js +29 -9
  157. package/esm/paginator/paginator.d.ts +38 -0
  158. package/esm/paginator/paginator.js +46 -0
  159. package/esm/popover/popover-adapter.js +1 -1
  160. package/esm/popover/popover-constants.d.ts +4 -0
  161. package/esm/popover/popover-constants.js +4 -2
  162. package/esm/popover/popover-core.d.ts +5 -1
  163. package/esm/popover/popover-core.js +13 -0
  164. package/esm/popover/popover.d.ts +6 -2
  165. package/esm/popover/popover.js +10 -2
  166. package/esm/profile-card/profile-card.d.ts +3 -0
  167. package/esm/profile-card/profile-card.js +3 -0
  168. package/esm/radio/radio/radio.d.ts +1 -2
  169. package/esm/radio/radio/radio.js +1 -2
  170. package/esm/scaffold/scaffold.d.ts +1 -1
  171. package/esm/scaffold/scaffold.js +1 -1
  172. package/esm/select/core/base-select-constants.d.ts +4 -0
  173. package/esm/select/core/base-select-core.d.ts +22 -2
  174. package/esm/select/core/base-select-core.js +217 -40
  175. package/esm/select/option/option.d.ts +2 -0
  176. package/esm/select/option/option.js +2 -0
  177. package/esm/select/option-group/option-group.d.ts +2 -0
  178. package/esm/select/option-group/option-group.js +2 -0
  179. package/esm/select/select/select-constants.d.ts +5 -0
  180. package/esm/select/select/select-constants.js +5 -2
  181. package/esm/select/select/select.d.ts +14 -2
  182. package/esm/select/select/select.js +23 -2
  183. package/esm/select/select-dropdown/select-dropdown.d.ts +2 -0
  184. package/esm/select/select-dropdown/select-dropdown.js +2 -0
  185. package/esm/skeleton/skeleton.d.ts +1 -1
  186. package/esm/skeleton/skeleton.js +1 -1
  187. package/esm/skip-link/skip-link.d.ts +1 -1
  188. package/esm/skip-link/skip-link.js +1 -1
  189. package/esm/slider/slider.d.ts +1 -1
  190. package/esm/slider/slider.js +1 -1
  191. package/esm/split-button/split-button.d.ts +1 -1
  192. package/esm/split-button/split-button.js +2 -2
  193. package/esm/split-view/split-view/split-view.d.ts +2 -0
  194. package/esm/split-view/split-view/split-view.js +2 -0
  195. package/esm/split-view/split-view-panel/split-view-panel.d.ts +2 -0
  196. package/esm/split-view/split-view-panel/split-view-panel.js +3 -1
  197. package/esm/stack/stack.d.ts +1 -8
  198. package/esm/stack/stack.js +1 -8
  199. package/esm/state-layer/state-layer.d.ts +1 -1
  200. package/esm/state-layer/state-layer.js +2 -2
  201. package/esm/stepper/step/step.d.ts +2 -0
  202. package/esm/stepper/step/step.js +3 -1
  203. package/esm/stepper/stepper/stepper.d.ts +2 -0
  204. package/esm/stepper/stepper/stepper.js +2 -0
  205. package/esm/table/table-adapter.d.ts +4 -4
  206. package/esm/table/table-adapter.js +4 -4
  207. package/esm/table/table-core.js +2 -2
  208. package/esm/table/table-utils.d.ts +2 -2
  209. package/esm/table/table-utils.js +25 -18
  210. package/esm/table/table.d.ts +3 -1
  211. package/esm/table/table.js +4 -1
  212. package/esm/tabs/tab/tab-adapter.js +2 -2
  213. package/esm/tabs/tab/tab.d.ts +2 -0
  214. package/esm/tabs/tab/tab.js +2 -0
  215. package/esm/tabs/tab-bar/tab-bar.d.ts +1 -1
  216. package/esm/tabs/tab-bar/tab-bar.js +1 -1
  217. package/esm/text-field/text-field-adapter.d.ts +6 -4
  218. package/esm/text-field/text-field-adapter.js +11 -4
  219. package/esm/text-field/text-field-core.d.ts +4 -0
  220. package/esm/text-field/text-field-core.js +13 -2
  221. package/esm/text-field/text-field.d.ts +1 -1
  222. package/esm/text-field/text-field.js +1 -1
  223. package/esm/time-picker/time-picker-adapter.js +1 -0
  224. package/esm/time-picker/time-picker-core.js +3 -3
  225. package/esm/time-picker/time-picker.d.ts +2 -0
  226. package/esm/time-picker/time-picker.js +2 -0
  227. package/esm/toast/toast-adapter.d.ts +20 -0
  228. package/esm/toast/toast-adapter.js +30 -0
  229. package/esm/toast/toast-core.d.ts +17 -0
  230. package/esm/toast/toast-core.js +66 -0
  231. package/esm/toast/toast.d.ts +9 -2
  232. package/esm/toast/toast.js +10 -1
  233. package/esm/toolbar/toolbar.d.ts +1 -3
  234. package/esm/toolbar/toolbar.js +1 -3
  235. package/esm/tooltip/tooltip-adapter.d.ts +6 -0
  236. package/esm/tooltip/tooltip-adapter.js +9 -0
  237. package/esm/tooltip/tooltip-constants.d.ts +1 -0
  238. package/esm/tooltip/tooltip-constants.js +2 -1
  239. package/esm/tooltip/tooltip-core.d.ts +20 -0
  240. package/esm/tooltip/tooltip-core.js +96 -2
  241. package/esm/tooltip/tooltip.d.ts +1 -1
  242. package/esm/tooltip/tooltip.js +2 -2
  243. package/esm/view-switcher/view/view.d.ts +2 -0
  244. package/esm/view-switcher/view/view.js +2 -0
  245. package/esm/view-switcher/view-switcher.d.ts +2 -0
  246. package/esm/view-switcher/view-switcher.js +2 -0
  247. package/package.json +4 -4
  248. package/sass/focus-indicator/focus-indicator.scss +1 -1
  249. package/sass/icon-button/forge-icon-button.scss +3 -3
  250. package/sass/list/forge-list.scss +6 -6
  251. package/sass/state-layer/_core.scss +2 -0
  252. package/sass/table/_core.scss +13 -1
  253. package/sass/tooltip/_core.scss +0 -2
  254. package/esm/focus-indicator/focus-indicator-adapter.d.ts +0 -29
  255. package/esm/focus-indicator/focus-indicator-adapter.js +0 -37
  256. package/esm/focus-indicator/focus-indicator-core.d.ts +0 -48
  257. package/esm/focus-indicator/focus-indicator-core.js +0 -129
@@ -39,8 +39,17 @@ export declare class TooltipCore extends TooltipCore_base implements ITooltipCor
39
39
  private _hoverStartListener;
40
40
  private _hoverEndListener;
41
41
  private _hoverTimeout;
42
+ private _hoverOutsideTimeout;
43
+ private _isHoveringTooltip;
44
+ private _isHoveringAnchor;
45
+ private _tooltipHoverStartListener;
46
+ private _tooltipHoverEndListener;
47
+ private _anchorOpenHoverStartListener;
48
+ private _anchorOpenHoverEndListener;
42
49
  private _focusListener;
43
50
  private _blurListener;
51
+ private _keyboardFocusListener;
52
+ private _keyboardBlurListener;
44
53
  private _longpressVisibilityTimeout;
45
54
  private _scrollListener;
46
55
  private _mouseDownListener;
@@ -56,10 +65,21 @@ export declare class TooltipCore extends TooltipCore_base implements ITooltipCor
56
65
  private _hide;
57
66
  private _attachDismissListeners;
58
67
  private _detachDismissListeners;
68
+ private _attachTooltipHoverListeners;
69
+ private _detachTooltipHoverListeners;
70
+ private _attachAnchorOpenHoverListeners;
71
+ private _detachAnchorOpenHoverListeners;
59
72
  private _onHoverStart;
60
73
  private _onHoverEnd;
61
74
  private _onFocus;
62
75
  private _onBlur;
76
+ private _onKeyboardFocus;
77
+ private _onKeyboardBlur;
78
+ private _onTooltipHoverStart;
79
+ private _onTooltipHoverEnd;
80
+ private _onAnchorOpenHoverStart;
81
+ private _onAnchorOpenHoverEnd;
82
+ private _scheduleHideIfOutsideHoverRegion;
63
83
  protected _onLongpress(): void;
64
84
  protected _onLongpressEnd(evt: PointerEvent | TouchEvent): void;
65
85
  private _onTryShow;
@@ -24,9 +24,20 @@ export class TooltipCore extends WithLongpressListener(Object) {
24
24
  // Hover trigger type
25
25
  this._hoverStartListener = this._onHoverStart.bind(this);
26
26
  this._hoverEndListener = this._onHoverEnd.bind(this);
27
+ this._isHoveringTooltip = false;
28
+ this._isHoveringAnchor = false;
29
+ // Tooltip hover listeners
30
+ this._tooltipHoverStartListener = this._onTooltipHoverStart.bind(this);
31
+ this._tooltipHoverEndListener = this._onTooltipHoverEnd.bind(this);
32
+ // Anchor hover listeners (when tooltip is open)
33
+ this._anchorOpenHoverStartListener = this._onAnchorOpenHoverStart.bind(this);
34
+ this._anchorOpenHoverEndListener = this._onAnchorOpenHoverEnd.bind(this);
27
35
  // Focus trigger type
28
36
  this._focusListener = this._onFocus.bind(this);
29
37
  this._blurListener = this._onBlur.bind(this);
38
+ // Keyboard-only focus for hover trigger (when focus trigger is not explicitly enabled)
39
+ this._keyboardFocusListener = this._onKeyboardFocus.bind(this);
40
+ this._keyboardBlurListener = this._onKeyboardBlur.bind(this);
30
41
  // Dismiss/hide triggers
31
42
  this._scrollListener = this._onTryHide.bind(this);
32
43
  this._mouseDownListener = this._onTryHide.bind(this);
@@ -66,7 +77,13 @@ export class TooltipCore extends WithLongpressListener(Object) {
66
77
  triggerTypes.push('longpress');
67
78
  }
68
79
  const triggerInitializers = {
69
- hover: () => this._adapter.addAnchorListener('mouseenter', this._hoverStartListener),
80
+ hover: () => {
81
+ this._adapter.addAnchorListener('mouseenter', this._hoverStartListener);
82
+ // Add keyboard focus support if focus trigger is not explicitly enabled
83
+ if (!triggerTypes.includes('focus')) {
84
+ this._adapter.addAnchorListener('focusin', this._keyboardFocusListener);
85
+ }
86
+ },
70
87
  longpress: () => this._startLongpressListener(this._adapter.anchorElement),
71
88
  focus: () => this._adapter.addAnchorListener('focusin', this._focusListener)
72
89
  };
@@ -86,6 +103,11 @@ export class TooltipCore extends WithLongpressListener(Object) {
86
103
  this._adapter.removeAnchorListener('mouseenter', this._hoverStartListener);
87
104
  this._adapter.removeAnchorListener('mousedown', this._hoverEndListener);
88
105
  this._adapter.removeAnchorListener('mouseleave', this._hoverEndListener);
106
+ // Remove keyboard focus support if focus trigger is not explicitly enabled
107
+ if (!triggerTypes.includes('focus')) {
108
+ this._adapter.removeAnchorListener('focusin', this._keyboardFocusListener);
109
+ this._adapter.removeAnchorListener('focusout', this._keyboardBlurListener);
110
+ }
89
111
  },
90
112
  longpress: () => this._stopLongpressListener(this._adapter.anchorElement),
91
113
  focus: () => {
@@ -101,13 +123,20 @@ export class TooltipCore extends WithLongpressListener(Object) {
101
123
  }
102
124
  this._open = true;
103
125
  this._adapter.show();
126
+ this._attachTooltipHoverListeners();
127
+ this._attachAnchorOpenHoverListeners();
104
128
  DismissibleStack.instance.add(this._adapter.hostElement);
105
129
  this._attachDismissListeners();
106
130
  this._adapter.toggleHostAttribute(TOOLTIP_CONSTANTS.attributes.OPEN, this._open);
107
131
  }
108
132
  _hide() {
109
133
  window.clearTimeout(this._hoverTimeout);
134
+ window.clearTimeout(this._hoverOutsideTimeout);
110
135
  window.clearTimeout(this._longpressVisibilityTimeout);
136
+ this._isHoveringTooltip = false;
137
+ this._isHoveringAnchor = false;
138
+ this._detachTooltipHoverListeners();
139
+ this._detachAnchorOpenHoverListeners();
111
140
  this._open = false;
112
141
  this._adapter.hide();
113
142
  DismissibleStack.instance.remove(this._adapter.hostElement);
@@ -128,11 +157,35 @@ export class TooltipCore extends WithLongpressListener(Object) {
128
157
  this._adapter.removeDocumentListener('wheel', this._scrollListener);
129
158
  this._adapter.removeLightDismissListener(this._lightDismissListener);
130
159
  }
160
+ _attachTooltipHoverListeners() {
161
+ // Only attach hover listeners if hover is one of the active trigger types
162
+ if (this._triggerTypes.includes('hover')) {
163
+ this._adapter.addTooltipListener('mouseenter', this._tooltipHoverStartListener);
164
+ this._adapter.addTooltipListener('mouseleave', this._tooltipHoverEndListener);
165
+ }
166
+ }
167
+ _detachTooltipHoverListeners() {
168
+ this._adapter.removeTooltipListener('mouseenter', this._tooltipHoverStartListener);
169
+ this._adapter.removeTooltipListener('mouseleave', this._tooltipHoverEndListener);
170
+ }
171
+ _attachAnchorOpenHoverListeners() {
172
+ // Only attach hover listeners if hover is one of the active trigger types
173
+ if (this._triggerTypes.includes('hover')) {
174
+ this._adapter.addAnchorListener('mouseenter', this._anchorOpenHoverStartListener);
175
+ this._adapter.addAnchorListener('mouseleave', this._anchorOpenHoverEndListener);
176
+ }
177
+ }
178
+ _detachAnchorOpenHoverListeners() {
179
+ this._adapter.removeAnchorListener('mouseenter', this._anchorOpenHoverStartListener);
180
+ this._adapter.removeAnchorListener('mouseleave', this._anchorOpenHoverEndListener);
181
+ }
131
182
  _onHoverStart(_evt) {
132
183
  /* c8 ignore next 3 */
133
184
  if (this._open) {
134
185
  return;
135
186
  }
187
+ this._isHoveringAnchor = true;
188
+ window.clearTimeout(this._hoverOutsideTimeout);
136
189
  this._adapter.addAnchorListener('mousedown', this._hoverEndListener);
137
190
  this._adapter.addAnchorListener('mouseleave', this._hoverEndListener);
138
191
  if (this._delay) {
@@ -145,10 +198,11 @@ export class TooltipCore extends WithLongpressListener(Object) {
145
198
  }
146
199
  }
147
200
  _onHoverEnd(_evt) {
201
+ this._isHoveringAnchor = false;
148
202
  this._adapter.removeAnchorListener('mousedown', this._hoverEndListener);
149
203
  this._adapter.removeAnchorListener('mouseleave', this._hoverEndListener);
150
204
  window.clearTimeout(this._hoverTimeout);
151
- this._onTryHide();
205
+ this._scheduleHideIfOutsideHoverRegion();
152
206
  }
153
207
  _onFocus(_evt) {
154
208
  /* c8 ignore next 3 */
@@ -162,6 +216,46 @@ export class TooltipCore extends WithLongpressListener(Object) {
162
216
  this._adapter.removeAnchorListener('focusout', this._blurListener);
163
217
  this._onTryHide();
164
218
  }
219
+ _onKeyboardFocus(_evt) {
220
+ /* c8 ignore next 3 */
221
+ if (this._open) {
222
+ return;
223
+ }
224
+ // Only show tooltip if the focus is from keyboard (focus-visible)
225
+ if (this._adapter.isKeyboardFocused()) {
226
+ this._adapter.addAnchorListener('focusout', this._keyboardBlurListener);
227
+ this._onTryShow();
228
+ }
229
+ }
230
+ _onKeyboardBlur(_evt) {
231
+ this._adapter.removeAnchorListener('focusout', this._keyboardBlurListener);
232
+ this._onTryHide();
233
+ }
234
+ _onTooltipHoverStart(_evt) {
235
+ this._isHoveringTooltip = true;
236
+ window.clearTimeout(this._hoverOutsideTimeout);
237
+ }
238
+ _onTooltipHoverEnd(_evt) {
239
+ this._isHoveringTooltip = false;
240
+ this._scheduleHideIfOutsideHoverRegion();
241
+ }
242
+ _onAnchorOpenHoverStart(_evt) {
243
+ this._isHoveringAnchor = true;
244
+ window.clearTimeout(this._hoverOutsideTimeout);
245
+ }
246
+ _onAnchorOpenHoverEnd(_evt) {
247
+ this._isHoveringAnchor = false;
248
+ this._scheduleHideIfOutsideHoverRegion();
249
+ }
250
+ _scheduleHideIfOutsideHoverRegion() {
251
+ window.clearTimeout(this._hoverOutsideTimeout);
252
+ this._hoverOutsideTimeout = window.setTimeout(() => {
253
+ // Only hide if user is outside both anchor and tooltip
254
+ if (!this._isHoveringTooltip && !this._isHoveringAnchor) {
255
+ this._onTryHide();
256
+ }
257
+ }, TOOLTIP_CONSTANTS.numbers.HOVER_OUTSIDE_THRESHOLD);
258
+ }
165
259
  _onLongpress() {
166
260
  this._onTryShow();
167
261
  }
@@ -37,7 +37,7 @@ declare const TooltipComponent_base: import("..").AbstractConstructor<import("..
37
37
  /**
38
38
  * @tag forge-tooltip
39
39
  *
40
- * @summary Tooltips display information related to an element when the user hovers over an element.
40
+ * @summary Tooltips display information related to an element when the user focuses or hovers over an anchor element. Use tooltips to provide additional context or information about elements that may not be immediately apparent.
41
41
  *
42
42
  * @dependency forge-overlay
43
43
  *
@@ -15,11 +15,11 @@ import { WithDefaultAria } from '../core/mixins/internals/with-default-aria';
15
15
  import { WithElementInternals } from '../core/mixins/internals/with-element-internals';
16
16
  import { tryDismiss } from '../core/utils/dismissible-stack';
17
17
  const template = '<template><div class=\"forge-tooltip\" part=\"surface\"><slot></slot><div class=\"arrow\" part=\"arrow\"></div></div></template>';
18
- const styles = '@keyframes slidein{from{opacity:0;transform:translateX(var(--_tooltip-slidein-x)) translateY(var(--_tooltip-slidein-y))}to{opacity:1;transform:translateX(0) translateY(0)}}:host{display:contents;pointer-events:none}:host([hidden]){display:none}.forge-tooltip{--_tooltip-background:var(--forge-tooltip-background, var(--forge-theme-surface-inverse, #333333));--_tooltip-color:var(--forge-tooltip-color, var(--forge-theme-on-surface-inverse, #ffffff));--_tooltip-shape:var(--forge-tooltip-shape, calc(var(--forge-shape-medium, 4px) * var(--forge-shape-factor, 1)));--_tooltip-padding:var(--forge-tooltip-padding, var(--forge-spacing-xsmall, 8px));--_tooltip-padding-block:var(--forge-tooltip-padding-block, var(--_tooltip-padding));--_tooltip-padding-inline:var(--forge-tooltip-padding-inline, var(--_tooltip-padding));--_tooltip-width:var(--forge-tooltip-width, max-content);--_tooltip-max-width:var(--forge-tooltip-max-width, 320px);--_tooltip-elevation:var(--forge-tooltip-elevation, var(--forge-theme-surface-bright-shadow, 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12)));--_tooltip-content-align:var(--forge-tooltip-content-align, center);--_tooltip-border-width:var(--forge-tooltip-border-width, 0);--_tooltip-border-style:var(--forge-tooltip-border-style, solid);--_tooltip-border-color:var(--forge-tooltip-border-color, var(--forge-theme-outline, #e0e0e0));--_tooltip-animation-timing:var(--forge-tooltip-animation-timing, var(--forge-animation-easing-decelerate, cubic-bezier(0, 0, 0, 1)));--_tooltip-animation-duration:var(--forge-tooltip-animation-duration, var(--forge-animation-duration-short3, 150ms));--_tooltip-animation-offset:var(--forge-tooltip-animation-offset, 24px);--_tooltip-arrow-size:var(--forge-tooltip-arrow-size, 8px);--_tooltip-arrow-height:var(--forge-tooltip-arrow-height, var(--_tooltip-arrow-size));--_tooltip-arrow-width:var(--forge-tooltip-arrow-width, var(--_tooltip-arrow-size));--_tooltip-arrow-shape:var(--forge-tooltip-arrow-shape, calc(var(--forge-shape-small, 2px) * var(--forge-shape-factor, 1)));--_tooltip-arrow-rotation:var(--forge-tooltip-arrow-rotation, 0deg);--_tooltip-arrow-top-rotation:var(--forge-tooltip-arrow-top-rotation, 315deg);--_tooltip-arrow-right-rotation:var(--forge-tooltip-arrow-right-rotation, 45deg);--_tooltip-arrow-bottom-rotation:var(--forge-tooltip-arrow-bottom-rotation, 135deg);--_tooltip-arrow-left-rotation:var(--forge-tooltip-arrow-left-rotation, 225deg)}.forge-tooltip{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--forge-typography-body1-font-family, var(--forge-typography-font-family, \"Roboto\", sans-serif));font-size:var(--forge-typography-body1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, .875)));font-weight:var(--forge-typography-body1-font-weight,400);line-height:var(--forge-typography-body1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.125)));letter-spacing:var(--forge-typography-body1-letter-spacing, .0357142857em);text-transform:var(--forge-typography-body1-text-transform,inherit);text-decoration:var(--forge-typography-body1-text-decoration,inherit);position:relative;background:var(--_tooltip-background);color:var(--_tooltip-color);border-radius:var(--_tooltip-shape);border-width:var(--_tooltip-border-width);border-style:var(--_tooltip-border-style);border-color:var(--_tooltip-border-color);padding-block:var(--_tooltip-padding-block);padding-inline:var(--_tooltip-padding-inline);box-shadow:var(--_tooltip-elevation);width:var(--_tooltip-width);max-width:var(--_tooltip-max-width);pointer-events:none;text-align:var(--_tooltip-content-align);line-height:normal;white-space:normal;animation-duration:var(--_tooltip-animation-duration);animation-timing-function:var(--_tooltip-animation-timing);animation-name:slidein;animation-fill-mode:forwards}:host(:not([open])) .forge-tooltip{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0}.arrow{position:absolute;contain:strict;background-color:inherit;height:var(--_tooltip-arrow-height);width:var(--_tooltip-arrow-width);box-shadow:inherit;border:inherit;border-end-start-radius:var(--_tooltip-arrow-shape);rotate:var(--_tooltip-arrow-rotation);clip-path:var(--_tooltip-arrow-clip-path);--_tooltip-arrow-translate-x:0;--_tooltip-arrow-translate-y:0;--_tooltip-arrow-clip-path:polygon(0 0, 0 100%, 100% 100%)}.forge-tooltip{--_tooltip-slidein-x:0;--_tooltip-slidein-y:0}forge-overlay[open][position-placement^=top] .forge-tooltip{--_tooltip-slidein-y:var(--forge-tooltip-slidein-y, var(--_tooltip-animation-offset))}forge-overlay[open][position-placement^=top] .arrow{--_tooltip-arrow-rotation:var(--_tooltip-arrow-top-rotation);margin-block-end:var(--_tooltip-border-width)}forge-overlay[open][position-placement^=right] .forge-tooltip{--_tooltip-slidein-x:var(--forge-tooltip-slidein-x, calc(var(--_tooltip-animation-offset) * -1))}forge-overlay[open][position-placement^=right] .arrow{--_tooltip-arrow-rotation:var(--_tooltip-arrow-right-rotation);margin-inline-start:var(--_tooltip-border-width)}forge-overlay[open][position-placement^=bottom] .forge-tooltip{--_tooltip-slidein-y:var(--forge-tooltip-slidein-y, calc(var(--_tooltip-animation-offset) * -1))}forge-overlay[open][position-placement^=bottom] .arrow{--_tooltip-arrow-rotation:var(--_tooltip-arrow-bottom-rotation);margin-block-start:var(--_tooltip-border-width)}forge-overlay[open][position-placement^=left] .forge-tooltip{--_tooltip-slidein-x:var(--forge-tooltip-slidein-x, var(--_tooltip-animation-offset))}forge-overlay[open][position-placement^=left] .arrow{--_tooltip-arrow-rotation:var(--_tooltip-arrow-left-rotation);margin-inline-end:var(--_tooltip-border-width)}';
18
+ const styles = '@keyframes slidein{from{opacity:0;transform:translateX(var(--_tooltip-slidein-x)) translateY(var(--_tooltip-slidein-y))}to{opacity:1;transform:translateX(0) translateY(0)}}:host{display:contents}:host([hidden]){display:none}.forge-tooltip{--_tooltip-background:var(--forge-tooltip-background, var(--forge-theme-surface-inverse, #333333));--_tooltip-color:var(--forge-tooltip-color, var(--forge-theme-on-surface-inverse, #ffffff));--_tooltip-shape:var(--forge-tooltip-shape, calc(var(--forge-shape-medium, 4px) * var(--forge-shape-factor, 1)));--_tooltip-padding:var(--forge-tooltip-padding, var(--forge-spacing-xsmall, 8px));--_tooltip-padding-block:var(--forge-tooltip-padding-block, var(--_tooltip-padding));--_tooltip-padding-inline:var(--forge-tooltip-padding-inline, var(--_tooltip-padding));--_tooltip-width:var(--forge-tooltip-width, max-content);--_tooltip-max-width:var(--forge-tooltip-max-width, 320px);--_tooltip-elevation:var(--forge-tooltip-elevation, var(--forge-theme-surface-bright-shadow, 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12)));--_tooltip-content-align:var(--forge-tooltip-content-align, center);--_tooltip-border-width:var(--forge-tooltip-border-width, 0);--_tooltip-border-style:var(--forge-tooltip-border-style, solid);--_tooltip-border-color:var(--forge-tooltip-border-color, var(--forge-theme-outline, #e0e0e0));--_tooltip-animation-timing:var(--forge-tooltip-animation-timing, var(--forge-animation-easing-decelerate, cubic-bezier(0, 0, 0, 1)));--_tooltip-animation-duration:var(--forge-tooltip-animation-duration, var(--forge-animation-duration-short3, 150ms));--_tooltip-animation-offset:var(--forge-tooltip-animation-offset, 24px);--_tooltip-arrow-size:var(--forge-tooltip-arrow-size, 8px);--_tooltip-arrow-height:var(--forge-tooltip-arrow-height, var(--_tooltip-arrow-size));--_tooltip-arrow-width:var(--forge-tooltip-arrow-width, var(--_tooltip-arrow-size));--_tooltip-arrow-shape:var(--forge-tooltip-arrow-shape, calc(var(--forge-shape-small, 2px) * var(--forge-shape-factor, 1)));--_tooltip-arrow-rotation:var(--forge-tooltip-arrow-rotation, 0deg);--_tooltip-arrow-top-rotation:var(--forge-tooltip-arrow-top-rotation, 315deg);--_tooltip-arrow-right-rotation:var(--forge-tooltip-arrow-right-rotation, 45deg);--_tooltip-arrow-bottom-rotation:var(--forge-tooltip-arrow-bottom-rotation, 135deg);--_tooltip-arrow-left-rotation:var(--forge-tooltip-arrow-left-rotation, 225deg)}.forge-tooltip{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--forge-typography-body1-font-family, var(--forge-typography-font-family, \"Roboto\", sans-serif));font-size:var(--forge-typography-body1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, .875)));font-weight:var(--forge-typography-body1-font-weight,400);line-height:var(--forge-typography-body1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.125)));letter-spacing:var(--forge-typography-body1-letter-spacing, .0357142857em);text-transform:var(--forge-typography-body1-text-transform,inherit);text-decoration:var(--forge-typography-body1-text-decoration,inherit);position:relative;background:var(--_tooltip-background);color:var(--_tooltip-color);border-radius:var(--_tooltip-shape);border-width:var(--_tooltip-border-width);border-style:var(--_tooltip-border-style);border-color:var(--_tooltip-border-color);padding-block:var(--_tooltip-padding-block);padding-inline:var(--_tooltip-padding-inline);box-shadow:var(--_tooltip-elevation);width:var(--_tooltip-width);max-width:var(--_tooltip-max-width);text-align:var(--_tooltip-content-align);line-height:normal;white-space:normal;animation-duration:var(--_tooltip-animation-duration);animation-timing-function:var(--_tooltip-animation-timing);animation-name:slidein;animation-fill-mode:forwards}:host(:not([open])) .forge-tooltip{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;border:0}.arrow{position:absolute;contain:strict;background-color:inherit;height:var(--_tooltip-arrow-height);width:var(--_tooltip-arrow-width);box-shadow:inherit;border:inherit;border-end-start-radius:var(--_tooltip-arrow-shape);rotate:var(--_tooltip-arrow-rotation);clip-path:var(--_tooltip-arrow-clip-path);--_tooltip-arrow-translate-x:0;--_tooltip-arrow-translate-y:0;--_tooltip-arrow-clip-path:polygon(0 0, 0 100%, 100% 100%)}.forge-tooltip{--_tooltip-slidein-x:0;--_tooltip-slidein-y:0}forge-overlay[open][position-placement^=top] .forge-tooltip{--_tooltip-slidein-y:var(--forge-tooltip-slidein-y, var(--_tooltip-animation-offset))}forge-overlay[open][position-placement^=top] .arrow{--_tooltip-arrow-rotation:var(--_tooltip-arrow-top-rotation);margin-block-end:var(--_tooltip-border-width)}forge-overlay[open][position-placement^=right] .forge-tooltip{--_tooltip-slidein-x:var(--forge-tooltip-slidein-x, calc(var(--_tooltip-animation-offset) * -1))}forge-overlay[open][position-placement^=right] .arrow{--_tooltip-arrow-rotation:var(--_tooltip-arrow-right-rotation);margin-inline-start:var(--_tooltip-border-width)}forge-overlay[open][position-placement^=bottom] .forge-tooltip{--_tooltip-slidein-y:var(--forge-tooltip-slidein-y, calc(var(--_tooltip-animation-offset) * -1))}forge-overlay[open][position-placement^=bottom] .arrow{--_tooltip-arrow-rotation:var(--_tooltip-arrow-bottom-rotation);margin-block-start:var(--_tooltip-border-width)}forge-overlay[open][position-placement^=left] .forge-tooltip{--_tooltip-slidein-x:var(--forge-tooltip-slidein-x, var(--_tooltip-animation-offset))}forge-overlay[open][position-placement^=left] .arrow{--_tooltip-arrow-rotation:var(--_tooltip-arrow-left-rotation);margin-inline-end:var(--_tooltip-border-width)}';
19
19
  /**
20
20
  * @tag forge-tooltip
21
21
  *
22
- * @summary Tooltips display information related to an element when the user hovers over an element.
22
+ * @summary Tooltips display information related to an element when the user focuses or hovers over an anchor element. Use tooltips to provide additional context or information about elements that may not be immediately apparent.
23
23
  *
24
24
  * @dependency forge-overlay
25
25
  *
@@ -12,6 +12,8 @@ declare global {
12
12
  }
13
13
  }
14
14
  /**
15
+ * @summary Represents a single view content area within a view-switcher for organizing and displaying content sections.
16
+ *
15
17
  * @tag forge-view
16
18
  */
17
19
  export declare class ViewComponent extends BaseComponent implements IViewComponent {
@@ -10,6 +10,8 @@ import { VIEW_CONSTANTS } from './view-constants';
10
10
  const template = '<template><slot></slot></template>';
11
11
  const styles = ':host{display:block}:host([hidden]){display:none}';
12
12
  /**
13
+ * @summary Represents a single view content area within a view-switcher for organizing and displaying content sections.
14
+ *
13
15
  * @tag forge-view
14
16
  */
15
17
  let ViewComponent = class ViewComponent extends BaseComponent {
@@ -19,6 +19,8 @@ declare global {
19
19
  }
20
20
  }
21
21
  /**
22
+ * @summary A container component that manages switching between multiple child `<forge-view>` elements with configurable animations and programmatic navigation controls.
23
+ *
22
24
  * @tag forge-view-switcher
23
25
  *
24
26
  * @dependency forge-view
@@ -13,6 +13,8 @@ import { BaseComponent } from '../core/base/base-component';
13
13
  const template = '<template><div class=\"forge-view-switcher\" part=\"root\"><slot></slot></div></template>';
14
14
  const styles = ':host{height:var(--_view-switcher-height);width:var(--_view-switcher-width);display:block}:host{--_view-switcher-height:var(--forge-view-switcher-height, auto);--_view-switcher-width:var(--forge-view-switcher-width, auto)}:host([hidden]){display:none}.forge-view-switcher{--_view-switcher-animation-duration:var(--forge-view-switcher-animation-duration, var(--forge-animation-duration-medium2, 300ms));--_view-switcher-animation-easing:var(--forge-view-switcher-animation-easing, var(--forge-animation-easing-standard, cubic-bezier(0.2, 0, 0, 1)))}.forge-view-switcher{height:var(--_view-switcher-height);width:var(--_view-switcher-width);position:relative;overflow:hidden;transition-property:height;transition-duration:var(--_view-switcher-animation-duration);transition-timing-function:var(--_view-switcher-animation-easing)}.forge-view-switcher ::slotted(.forge-view-switcher__view--hidden){position:absolute;top:0;right:0;bottom:0;left:0}:host(.slide) ::slotted(forge-view){transition-property:transform;transition-duration:var(--_view-switcher-animation-duration);transition-timing-function:var(--_view-switcher-animation-easing);will-change:transform}:host(.fade) ::slotted(forge-view){transition-property:opacity;transition-duration:var(--_view-switcher-animation-duration);transition-timing-function:var(--_view-switcher-animation-easing);will-change:opacity}:host(.fade) ::slotted(.forge-view-switcher__view--hidden){opacity:0}';
15
15
  /**
16
+ * @summary A container component that manages switching between multiple child `<forge-view>` elements with configurable animations and programmatic navigation controls.
17
+ *
16
18
  * @tag forge-view-switcher
17
19
  *
18
20
  * @dependency forge-view
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tylertech/forge",
3
3
  "description": "Tyler Forge™ Web Components library",
4
- "version": "3.10.5",
4
+ "version": "3.12.0",
5
5
  "author": "Tyler Technologies, Inc.",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -13,11 +13,11 @@
13
13
  "typings": "esm/index.d.ts",
14
14
  "sideEffects": false,
15
15
  "dependencies": {
16
- "@floating-ui/dom": "^1.7.1",
16
+ "@floating-ui/dom": "^1.7.4",
17
17
  "@tylertech/forge-core": "^3.2.1",
18
- "@tylertech/tyler-icons": "^2.0.3",
18
+ "@tylertech/tyler-icons": "^2.0.4",
19
19
  "imask": "^7.6.1",
20
- "lit": "^3.3.0",
20
+ "lit": "^3.3.1",
21
21
  "tslib": "^2.8.1"
22
22
  },
23
23
  "customElements": "custom-elements.json"
@@ -26,7 +26,7 @@
26
26
  // States
27
27
  //
28
28
 
29
- :host([active]) {
29
+ :host(:where(:state(active), [active])) {
30
30
  @include active;
31
31
  }
32
32
 
@@ -47,9 +47,9 @@
47
47
  );
48
48
 
49
49
  &:where(
50
- .forge-icon-button--text,
51
- :not(:where(.forge-icon-button--outlined, .forge-icon-button--tonal, .forge-icon-button--filled, .forge-icon-button--raised))
52
- ) {
50
+ .forge-icon-button--text,
51
+ :not(:where(.forge-icon-button--outlined, .forge-icon-button--tonal, .forge-icon-button--filled, .forge-icon-button--raised))
52
+ ) {
53
53
  @include focus-indicator.provide-theme(
54
54
  (
55
55
  outward-offset: 0px // Requires unit
@@ -118,12 +118,12 @@
118
118
  }
119
119
 
120
120
  &:has(
121
- button:not(:disabled),
122
- a,
123
- label,
124
- .forge-list-item--interactive:not(.forge-list-item--disabled),
125
- :is(forge-checkbox, forge-radio, forge-switch, input):not([disabled])
126
- ) {
121
+ button:not(:disabled),
122
+ a,
123
+ label,
124
+ .forge-list-item--interactive:not(.forge-list-item--disabled),
125
+ :is(forge-checkbox, forge-radio, forge-switch, input):not([disabled])
126
+ ) {
127
127
  a,
128
128
  button,
129
129
  label,
@@ -57,6 +57,8 @@
57
57
  @mixin layer-base {
58
58
  opacity: 0;
59
59
  position: absolute;
60
+ backface-visibility: hidden;
61
+ transform: translateZ(0);
60
62
  }
61
63
 
62
64
  @mixin hover-base {
@@ -9,6 +9,7 @@
9
9
  @use '../core/styles/theme';
10
10
  @use '../core/styles/typography';
11
11
  @use '../core/styles/animation';
12
+ @use '../focus-indicator';
12
13
  @use './variables';
13
14
 
14
15
  @mixin host {
@@ -239,7 +240,18 @@
239
240
  font: inherit;
240
241
  color: inherit;
241
242
  width: 100%;
242
- outline-offset: #{spacing.variable(xxsmall)};
243
+ outline: none;
244
+ position: relative;
245
+
246
+ forge-focus-indicator {
247
+ border-radius: 4px;
248
+
249
+ @include focus-indicator.provide-theme(
250
+ (
251
+ 'offset-inline': -4px
252
+ )
253
+ );
254
+ }
243
255
  }
244
256
 
245
257
  // The base table body row styles for row interactions.
@@ -11,7 +11,6 @@
11
11
 
12
12
  @mixin host {
13
13
  display: contents;
14
- pointer-events: none;
15
14
  }
16
15
 
17
16
  @mixin base {
@@ -32,7 +31,6 @@
32
31
 
33
32
  width: #{token(width)};
34
33
  max-width: #{token(max-width)};
35
- pointer-events: none;
36
34
  text-align: #{token(content-align)};
37
35
  line-height: normal;
38
36
  white-space: normal;
@@ -1,29 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Tyler Technologies, Inc.
4
- * License: Apache-2.0
5
- */
6
- import { BaseAdapter, IBaseAdapter } from '../core';
7
- import { IFocusIndicatorComponent } from './focus-indicator';
8
- export interface IFocusIndicatorAdapter extends IBaseAdapter {
9
- destroy(): void;
10
- hasTargetElement(): boolean;
11
- addTargetListener(type: string, listener: EventListener): void;
12
- removeTargetListener(type: string, listener: EventListener): void;
13
- getTargetElement(): HTMLElement | null;
14
- setTargetElement(el: HTMLElement | null): void;
15
- trySetTarget(value: string | null): void;
16
- isActive(selector: string, el?: HTMLElement | null): boolean;
17
- }
18
- export declare class FocusIndicatorAdapter extends BaseAdapter<IFocusIndicatorComponent> implements IFocusIndicatorAdapter {
19
- private _targetElement;
20
- constructor(component: IFocusIndicatorComponent);
21
- destroy(): void;
22
- hasTargetElement(): boolean;
23
- addTargetListener(type: string, listener: EventListener): void;
24
- removeTargetListener(type: string, listener: EventListener): void;
25
- getTargetElement(): HTMLElement | null;
26
- setTargetElement(el: HTMLElement | null): void;
27
- trySetTarget(value: string | null): void;
28
- isActive(selector: string, el?: HTMLElement | null): boolean;
29
- }
@@ -1,37 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Tyler Technologies, Inc.
4
- * License: Apache-2.0
5
- */
6
- import { BaseAdapter, locateTargetHeuristic } from '../core';
7
- export class FocusIndicatorAdapter extends BaseAdapter {
8
- constructor(component) {
9
- super(component);
10
- this._targetElement = null;
11
- }
12
- destroy() {
13
- this._targetElement = null;
14
- }
15
- hasTargetElement() {
16
- return !!this._targetElement;
17
- }
18
- addTargetListener(type, listener) {
19
- this._targetElement?.addEventListener(type, listener);
20
- }
21
- removeTargetListener(type, listener) {
22
- this._targetElement?.removeEventListener(type, listener);
23
- }
24
- getTargetElement() {
25
- return this._targetElement;
26
- }
27
- setTargetElement(el) {
28
- this._targetElement = el;
29
- }
30
- trySetTarget(value) {
31
- this._targetElement = locateTargetHeuristic(this._component, value);
32
- }
33
- isActive(selector, el) {
34
- const targetedEl = el ?? this._targetElement;
35
- return !!targetedEl?.matches(selector);
36
- }
37
- }
@@ -1,48 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Tyler Technologies, Inc.
4
- * License: Apache-2.0
5
- */
6
- import { IFocusIndicatorAdapter } from './focus-indicator-adapter';
7
- import { FocusIndicatorFocusMode } from './focus-indicator-constants';
8
- export interface IFocusIndicatorCore {
9
- targetElement: HTMLElement | null;
10
- target: string | null;
11
- active: boolean;
12
- inward: boolean;
13
- circular: boolean;
14
- allowFocus: boolean;
15
- focusMode: FocusIndicatorFocusMode;
16
- initialize(): void;
17
- destroy(): void;
18
- }
19
- export declare class FocusIndicatorCore implements IFocusIndicatorCore {
20
- private _adapter;
21
- private _target;
22
- private _active;
23
- private _inward;
24
- private _circular;
25
- private _allowFocus;
26
- private _focusMode;
27
- private _interactionListener;
28
- constructor(_adapter: IFocusIndicatorAdapter);
29
- initialize(): void;
30
- destroy(): void;
31
- private _addListeners;
32
- private _removeListeners;
33
- private _onInteraction;
34
- get targetElement(): HTMLElement | null;
35
- set targetElement(value: HTMLElement | null);
36
- get target(): string | null;
37
- set target(value: string | null);
38
- get active(): boolean;
39
- set active(value: boolean);
40
- get inward(): boolean;
41
- set inward(value: boolean);
42
- get circular(): boolean;
43
- set circular(value: boolean);
44
- get allowFocus(): boolean;
45
- set allowFocus(value: boolean);
46
- get focusMode(): FocusIndicatorFocusMode;
47
- set focusMode(value: FocusIndicatorFocusMode);
48
- }
@@ -1,129 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright Tyler Technologies, Inc.
4
- * License: Apache-2.0
5
- */
6
- import { FOCUS_INDICATOR_CONSTANTS } from './focus-indicator-constants';
7
- export class FocusIndicatorCore {
8
- constructor(_adapter) {
9
- this._adapter = _adapter;
10
- this._target = null;
11
- this._active = false;
12
- this._inward = false;
13
- this._circular = false;
14
- this._allowFocus = false;
15
- this._focusMode = FOCUS_INDICATOR_CONSTANTS.defaults.FOCUS_MODE;
16
- this._interactionListener = evt => this._onInteraction(evt);
17
- }
18
- initialize() {
19
- if (!this._adapter.hasTargetElement()) {
20
- this._adapter.trySetTarget(this._target);
21
- }
22
- this._addListeners();
23
- }
24
- destroy() {
25
- this._removeListeners(); // Must be called before destroying adapter
26
- this._adapter.destroy();
27
- }
28
- _addListeners() {
29
- this._adapter.addTargetListener(this._focusMode, this._interactionListener);
30
- this._adapter.addTargetListener('focusout', this._interactionListener);
31
- this._adapter.addTargetListener('pointerdown', this._interactionListener);
32
- }
33
- _removeListeners() {
34
- this._adapter.removeTargetListener(this._focusMode, this._interactionListener);
35
- this._adapter.removeTargetListener('focusout', this._interactionListener);
36
- this._adapter.removeTargetListener('pointerdown', this._interactionListener);
37
- }
38
- _onInteraction(evt) {
39
- const target = evt.target;
40
- switch (evt.type) {
41
- case this._focusMode:
42
- this.active = this._adapter.isActive(this._allowFocus ? ':focus' : ':focus-visible', target);
43
- break;
44
- case 'focusout':
45
- this.active = false;
46
- break;
47
- case 'pointerdown':
48
- this.active = this._allowFocus ? this._adapter.isActive(':focus', target) : this._adapter.isActive(':focus-visible', target);
49
- break;
50
- }
51
- }
52
- get targetElement() {
53
- return this._adapter.getTargetElement();
54
- }
55
- set targetElement(value) {
56
- this._removeListeners();
57
- this._adapter.setTargetElement(value);
58
- this._addListeners();
59
- }
60
- get target() {
61
- return this._adapter.getHostAttribute(FOCUS_INDICATOR_CONSTANTS.attributes.TARGET);
62
- }
63
- set target(value) {
64
- if (this._target !== value) {
65
- this._target = value;
66
- if (this._adapter.isConnected) {
67
- this._adapter.trySetTarget(value);
68
- }
69
- this._adapter.toggleHostAttribute(FOCUS_INDICATOR_CONSTANTS.attributes.TARGET, Boolean(this._target), this._target);
70
- }
71
- }
72
- get active() {
73
- return this._active;
74
- }
75
- set active(value) {
76
- value = Boolean(value);
77
- if (this._active !== value) {
78
- this._active = value;
79
- this._adapter.toggleHostAttribute(FOCUS_INDICATOR_CONSTANTS.attributes.ACTIVE, this._active);
80
- }
81
- }
82
- get inward() {
83
- return this._inward;
84
- }
85
- set inward(value) {
86
- value = Boolean(value);
87
- if (this._inward !== value) {
88
- this._inward = value;
89
- this._adapter.toggleHostAttribute(FOCUS_INDICATOR_CONSTANTS.attributes.INWARD, this._inward);
90
- }
91
- }
92
- get circular() {
93
- return this._circular;
94
- }
95
- set circular(value) {
96
- value = Boolean(value);
97
- if (this._circular !== value) {
98
- this._circular = value;
99
- this._adapter.toggleHostAttribute(FOCUS_INDICATOR_CONSTANTS.attributes.CIRCULAR, this._circular);
100
- }
101
- }
102
- get allowFocus() {
103
- return this._allowFocus;
104
- }
105
- set allowFocus(value) {
106
- value = Boolean(value);
107
- if (this._allowFocus !== value) {
108
- this._allowFocus = value;
109
- this._adapter.toggleHostAttribute(FOCUS_INDICATOR_CONSTANTS.attributes.ALLOW_FOCUS, this._allowFocus);
110
- }
111
- }
112
- get focusMode() {
113
- return this._focusMode;
114
- }
115
- set focusMode(value) {
116
- value ?? (value = FOCUS_INDICATOR_CONSTANTS.defaults.FOCUS_MODE);
117
- if (this._focusMode !== value) {
118
- if (this._adapter.isConnected) {
119
- this._removeListeners();
120
- }
121
- this._focusMode = value;
122
- if (this._adapter.isConnected) {
123
- this._addListeners();
124
- }
125
- const hasFocusMode = this._focusMode !== FOCUS_INDICATOR_CONSTANTS.defaults.FOCUS_MODE;
126
- this._adapter.toggleHostAttribute(FOCUS_INDICATOR_CONSTANTS.attributes.FOCUS_MODE, hasFocusMode, this._focusMode);
127
- }
128
- }
129
- }