vira 28.19.5 → 28.19.6

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 (188) hide show
  1. package/package.json +12 -12
  2. package/src/elements/define-vira-element.ts +29 -0
  3. package/src/elements/form/vira-form-fields.ts +140 -0
  4. package/src/elements/form/vira-form.element.ts +204 -0
  5. package/src/elements/pop-up/pop-up-helpers.ts +85 -0
  6. package/{dist/elements/pop-up/pop-up-menu-item.d.ts → src/elements/pop-up/pop-up-menu-item.ts} +4 -3
  7. package/{dist/elements/pop-up/vira-menu-item.element.js → src/elements/pop-up/vira-menu-item.element.ts} +28 -11
  8. package/src/elements/pop-up/vira-menu-trigger.element.ts +158 -0
  9. package/{dist/elements/pop-up/vira-menu.element.js → src/elements/pop-up/vira-menu.element.ts} +76 -49
  10. package/{dist/elements/pop-up/vira-pop-up-menu.element.js → src/elements/pop-up/vira-pop-up-menu.element.ts} +34 -22
  11. package/{dist/elements/pop-up/vira-pop-up-trigger.element.js → src/elements/pop-up/vira-pop-up-trigger.element.ts} +199 -104
  12. package/src/elements/shared-text-input-logic.ts +173 -0
  13. package/{dist/elements/vira-bold-text.element.js → src/elements/vira-bold-text.element.ts} +8 -7
  14. package/{dist/elements/vira-button.element.js → src/elements/vira-button.element.ts} +64 -33
  15. package/{dist/elements/vira-card.element.js → src/elements/vira-card.element.ts} +16 -13
  16. package/{dist/elements/vira-checkbox.element.js → src/elements/vira-checkbox.element.ts} +71 -28
  17. package/{dist/elements/vira-collapsible-wrapper.element.js → src/elements/vira-collapsible-wrapper.element.ts} +18 -16
  18. package/{dist/elements/vira-dropdown.element.js → src/elements/vira-dropdown.element.ts} +94 -48
  19. package/{dist/elements/vira-error.element.js → src/elements/vira-error.element.ts} +6 -5
  20. package/{dist/elements/vira-icon.element.js → src/elements/vira-icon.element.ts} +13 -6
  21. package/{dist/elements/vira-image.element.js → src/elements/vira-image.element.ts} +63 -43
  22. package/{dist/elements/vira-input.element.js → src/elements/vira-input.element.ts} +151 -85
  23. package/{dist/elements/vira-link.element.js → src/elements/vira-link.element.ts} +62 -11
  24. package/{dist/elements/vira-modal.element.js → src/elements/vira-modal.element.ts} +89 -50
  25. package/src/elements/vira-overflow-switch.element.ts +137 -0
  26. package/{dist/elements/vira-progress.element.js → src/elements/vira-progress.element.ts} +26 -11
  27. package/{dist/elements/vira-select.element.js → src/elements/vira-select.element.ts} +96 -41
  28. package/src/icons/icon-color.test-helper.ts +9 -0
  29. package/{dist/icons/icon-css-vars.js → src/icons/icon-css-vars.ts} +2 -1
  30. package/src/icons/icon-svg.ts +71 -0
  31. package/{dist/icons/icon-svgs/bell-24.icon.js → src/icons/icon-svgs/bell-24.icon.ts} +5 -4
  32. package/{dist/icons/icon-svgs/chat-24.icon.js → src/icons/icon-svgs/chat-24.icon.ts} +5 -4
  33. package/{dist/icons/icon-svgs/check-24.icon.js → src/icons/icon-svgs/check-24.icon.ts} +5 -4
  34. package/{dist/icons/icon-svgs/chevron-down-24.icon.js → src/icons/icon-svgs/chevron-down-24.icon.ts} +5 -4
  35. package/{dist/icons/icon-svgs/chevron-up-24.icon.js → src/icons/icon-svgs/chevron-up-24.icon.ts} +5 -4
  36. package/{dist/icons/icon-svgs/close-x-24.icon.js → src/icons/icon-svgs/close-x-24.icon.ts} +5 -4
  37. package/{dist/icons/icon-svgs/commit-24.icon.js → src/icons/icon-svgs/commit-24.icon.ts} +5 -4
  38. package/{dist/icons/icon-svgs/copy-24.icon.js → src/icons/icon-svgs/copy-24.icon.ts} +5 -4
  39. package/{dist/icons/icon-svgs/document-24.icon.js → src/icons/icon-svgs/document-24.icon.ts} +5 -4
  40. package/{dist/icons/icon-svgs/document-search-24.icon.js → src/icons/icon-svgs/document-search-24.icon.ts} +5 -4
  41. package/{dist/icons/icon-svgs/double-chevron-24.icon.js → src/icons/icon-svgs/double-chevron-24.icon.ts} +5 -4
  42. package/{dist/icons/icon-svgs/element-16.icon.js → src/icons/icon-svgs/element-16.icon.ts} +5 -4
  43. package/{dist/icons/icon-svgs/element-24.icon.js → src/icons/icon-svgs/element-24.icon.ts} +5 -4
  44. package/{dist/icons/icon-svgs/external-link-24.icon.js → src/icons/icon-svgs/external-link-24.icon.ts} +5 -4
  45. package/{dist/icons/icon-svgs/eye-closed-24.icon.js → src/icons/icon-svgs/eye-closed-24.icon.ts} +5 -4
  46. package/{dist/icons/icon-svgs/eye-open-24.icon.js → src/icons/icon-svgs/eye-open-24.icon.ts} +5 -4
  47. package/{dist/icons/icon-svgs/filter-24.icon.js → src/icons/icon-svgs/filter-24.icon.ts} +5 -4
  48. package/{dist/icons/icon-svgs/link-24.icon.js → src/icons/icon-svgs/link-24.icon.ts} +5 -4
  49. package/{dist/icons/icon-svgs/loader-24.icon.js → src/icons/icon-svgs/loader-24.icon.ts} +5 -4
  50. package/{dist/icons/icon-svgs/loader-animated-24.icon.js → src/icons/icon-svgs/loader-animated-24.icon.ts} +8 -6
  51. package/{dist/icons/icon-svgs/lock-24.icon.js → src/icons/icon-svgs/lock-24.icon.ts} +5 -4
  52. package/{dist/icons/icon-svgs/options-24.icon.js → src/icons/icon-svgs/options-24.icon.ts} +5 -4
  53. package/{dist/icons/icon-svgs/pencil-24.icon.js → src/icons/icon-svgs/pencil-24.icon.ts} +5 -4
  54. package/{dist/icons/icon-svgs/shield-24.icon.js → src/icons/icon-svgs/shield-24.icon.ts} +5 -4
  55. package/{dist/icons/icon-svgs/sort-ascending-24.icon.js → src/icons/icon-svgs/sort-ascending-24.icon.ts} +5 -4
  56. package/{dist/icons/icon-svgs/sort-descending-24.icon.js → src/icons/icon-svgs/sort-descending-24.icon.ts} +5 -4
  57. package/{dist/icons/icon-svgs/speaker-loud-24.icon.js → src/icons/icon-svgs/speaker-loud-24.icon.ts} +5 -4
  58. package/{dist/icons/icon-svgs/speaker-medium-24.icon.js → src/icons/icon-svgs/speaker-medium-24.icon.ts} +5 -4
  59. package/{dist/icons/icon-svgs/speaker-muted-24.icon.js → src/icons/icon-svgs/speaker-muted-24.icon.ts} +5 -4
  60. package/{dist/icons/icon-svgs/speaker-quiet-24.icon.js → src/icons/icon-svgs/speaker-quiet-24.icon.ts} +5 -4
  61. package/{dist/icons/icon-svgs/star-24.icon.js → src/icons/icon-svgs/star-24.icon.ts} +5 -4
  62. package/{dist/icons/icon-svgs/status-failure-24.icon.js → src/icons/icon-svgs/status-failure-24.icon.ts} +5 -4
  63. package/{dist/icons/icon-svgs/status-in-progress-24.icon.js → src/icons/icon-svgs/status-in-progress-24.icon.ts} +5 -4
  64. package/{dist/icons/icon-svgs/status-success-24.icon.js → src/icons/icon-svgs/status-success-24.icon.ts} +5 -4
  65. package/{dist/icons/icon-svgs/status-unknown-24.icon.js → src/icons/icon-svgs/status-unknown-24.icon.ts} +5 -4
  66. package/{dist/icons/icon-svgs/status-warning-24.icon.js → src/icons/icon-svgs/status-warning-24.icon.ts} +5 -4
  67. package/{dist/icons/icon-svgs/upload-24.icon.js → src/icons/icon-svgs/upload-24.icon.ts} +5 -4
  68. package/{dist/icons/icon-svgs/x-24.icon.js → src/icons/icon-svgs/x-24.icon.ts} +5 -4
  69. package/{dist/icons/index.js → src/icons/index.ts} +43 -39
  70. package/{dist/styles/border.js → src/styles/border.ts} +2 -1
  71. package/{dist/styles/disabled.js → src/styles/disabled.ts} +3 -2
  72. package/{dist/styles/durations.js → src/styles/durations.ts} +2 -1
  73. package/{dist/styles/focus.js → src/styles/focus.ts} +32 -8
  74. package/{dist/styles/font.js → src/styles/font.ts} +2 -1
  75. package/{dist/styles/form-styles.js → src/styles/form-styles.ts} +6 -1
  76. package/{dist/styles/index.js → src/styles/index.ts} +1 -0
  77. package/{dist/styles/native-styles.js → src/styles/native-styles.ts} +5 -3
  78. package/{dist/styles/scrollbar.js → src/styles/scrollbar.ts} +4 -3
  79. package/{dist/styles/shadows.js → src/styles/shadows.ts} +8 -6
  80. package/{dist/styles/user-select.js → src/styles/user-select.ts} +3 -2
  81. package/{dist/styles/vira-color-palette.js → src/styles/vira-color-palette.ts} +11 -1
  82. package/src/styles/vira-color-theme.ts +1142 -0
  83. package/src/util/define-table.ts +279 -0
  84. package/src/util/dynamic-element.ts +129 -0
  85. package/src/util/pop-up-manager.ts +380 -0
  86. package/dist/elements/define-vira-element.d.ts +0 -18
  87. package/dist/elements/define-vira-element.js +0 -19
  88. package/dist/elements/form/vira-form-fields.d.ts +0 -100
  89. package/dist/elements/form/vira-form-fields.js +0 -60
  90. package/dist/elements/form/vira-form.element.d.ts +0 -35
  91. package/dist/elements/form/vira-form.element.js +0 -151
  92. package/dist/elements/index.js +0 -25
  93. package/dist/elements/pop-up/pop-up-helpers.d.ts +0 -33
  94. package/dist/elements/pop-up/pop-up-helpers.js +0 -58
  95. package/dist/elements/pop-up/pop-up-menu-item.js +0 -1
  96. package/dist/elements/pop-up/vira-menu-item.element.d.ts +0 -19
  97. package/dist/elements/pop-up/vira-menu-trigger.element.d.ts +0 -41
  98. package/dist/elements/pop-up/vira-menu-trigger.element.js +0 -121
  99. package/dist/elements/pop-up/vira-menu.element.d.ts +0 -38
  100. package/dist/elements/pop-up/vira-pop-up-menu.element.d.ts +0 -35
  101. package/dist/elements/pop-up/vira-pop-up-trigger.element.d.ts +0 -105
  102. package/dist/elements/shared-text-input-logic.d.ts +0 -63
  103. package/dist/elements/shared-text-input-logic.js +0 -101
  104. package/dist/elements/vira-bold-text.element.d.ts +0 -9
  105. package/dist/elements/vira-button.element.d.ts +0 -31
  106. package/dist/elements/vira-card.element.d.ts +0 -18
  107. package/dist/elements/vira-checkbox.element.d.ts +0 -34
  108. package/dist/elements/vira-collapsible-wrapper.element.d.ts +0 -14
  109. package/dist/elements/vira-dropdown.element.d.ts +0 -46
  110. package/dist/elements/vira-error.element.d.ts +0 -7
  111. package/dist/elements/vira-icon.element.d.ts +0 -13
  112. package/dist/elements/vira-image.element.d.ts +0 -45
  113. package/dist/elements/vira-input.element.d.ts +0 -62
  114. package/dist/elements/vira-link.element.d.ts +0 -73
  115. package/dist/elements/vira-modal.element.d.ts +0 -39
  116. package/dist/elements/vira-overflow-switch.element.d.ts +0 -21
  117. package/dist/elements/vira-overflow-switch.element.js +0 -110
  118. package/dist/elements/vira-progress.element.d.ts +0 -18
  119. package/dist/elements/vira-select.element.d.ts +0 -48
  120. package/dist/icons/icon-color.test-helper.d.ts +0 -6
  121. package/dist/icons/icon-color.test-helper.js +0 -9
  122. package/dist/icons/icon-css-vars.d.ts +0 -14
  123. package/dist/icons/icon-svg.d.ts +0 -27
  124. package/dist/icons/icon-svg.js +0 -48
  125. package/dist/icons/icon-svgs/bell-24.icon.d.ts +0 -8
  126. package/dist/icons/icon-svgs/chat-24.icon.d.ts +0 -8
  127. package/dist/icons/icon-svgs/check-24.icon.d.ts +0 -8
  128. package/dist/icons/icon-svgs/chevron-down-24.icon.d.ts +0 -8
  129. package/dist/icons/icon-svgs/chevron-up-24.icon.d.ts +0 -8
  130. package/dist/icons/icon-svgs/close-x-24.icon.d.ts +0 -8
  131. package/dist/icons/icon-svgs/commit-24.icon.d.ts +0 -8
  132. package/dist/icons/icon-svgs/copy-24.icon.d.ts +0 -8
  133. package/dist/icons/icon-svgs/document-24.icon.d.ts +0 -8
  134. package/dist/icons/icon-svgs/document-search-24.icon.d.ts +0 -8
  135. package/dist/icons/icon-svgs/double-chevron-24.icon.d.ts +0 -8
  136. package/dist/icons/icon-svgs/element-16.icon.d.ts +0 -8
  137. package/dist/icons/icon-svgs/element-24.icon.d.ts +0 -8
  138. package/dist/icons/icon-svgs/external-link-24.icon.d.ts +0 -8
  139. package/dist/icons/icon-svgs/eye-closed-24.icon.d.ts +0 -8
  140. package/dist/icons/icon-svgs/eye-open-24.icon.d.ts +0 -8
  141. package/dist/icons/icon-svgs/filter-24.icon.d.ts +0 -8
  142. package/dist/icons/icon-svgs/link-24.icon.d.ts +0 -8
  143. package/dist/icons/icon-svgs/loader-24.icon.d.ts +0 -8
  144. package/dist/icons/icon-svgs/loader-animated-24.icon.d.ts +0 -8
  145. package/dist/icons/icon-svgs/lock-24.icon.d.ts +0 -8
  146. package/dist/icons/icon-svgs/options-24.icon.d.ts +0 -8
  147. package/dist/icons/icon-svgs/pencil-24.icon.d.ts +0 -8
  148. package/dist/icons/icon-svgs/shield-24.icon.d.ts +0 -8
  149. package/dist/icons/icon-svgs/sort-ascending-24.icon.d.ts +0 -8
  150. package/dist/icons/icon-svgs/sort-descending-24.icon.d.ts +0 -8
  151. package/dist/icons/icon-svgs/speaker-loud-24.icon.d.ts +0 -8
  152. package/dist/icons/icon-svgs/speaker-medium-24.icon.d.ts +0 -8
  153. package/dist/icons/icon-svgs/speaker-muted-24.icon.d.ts +0 -8
  154. package/dist/icons/icon-svgs/speaker-quiet-24.icon.d.ts +0 -8
  155. package/dist/icons/icon-svgs/star-24.icon.d.ts +0 -8
  156. package/dist/icons/icon-svgs/status-failure-24.icon.d.ts +0 -8
  157. package/dist/icons/icon-svgs/status-in-progress-24.icon.d.ts +0 -8
  158. package/dist/icons/icon-svgs/status-success-24.icon.d.ts +0 -8
  159. package/dist/icons/icon-svgs/status-unknown-24.icon.d.ts +0 -8
  160. package/dist/icons/icon-svgs/status-warning-24.icon.d.ts +0 -8
  161. package/dist/icons/icon-svgs/upload-24.icon.d.ts +0 -8
  162. package/dist/icons/icon-svgs/x-24.icon.d.ts +0 -8
  163. package/dist/icons/index.d.ts +0 -86
  164. package/dist/index.js +0 -4
  165. package/dist/styles/border.d.ts +0 -9
  166. package/dist/styles/disabled.d.ts +0 -6
  167. package/dist/styles/durations.d.ts +0 -22
  168. package/dist/styles/focus.d.ts +0 -31
  169. package/dist/styles/font.d.ts +0 -9
  170. package/dist/styles/form-styles.d.ts +0 -20
  171. package/dist/styles/index.d.ts +0 -13
  172. package/dist/styles/native-styles.d.ts +0 -13
  173. package/dist/styles/scrollbar.d.ts +0 -6
  174. package/dist/styles/shadows.d.ts +0 -20
  175. package/dist/styles/user-select.d.ts +0 -6
  176. package/dist/styles/vira-color-palette.d.ts +0 -95
  177. package/dist/styles/vira-color-theme.d.ts +0 -1184
  178. package/dist/styles/vira-color-theme.js +0 -1137
  179. package/dist/util/define-table.d.ts +0 -110
  180. package/dist/util/define-table.js +0 -115
  181. package/dist/util/dynamic-element.d.ts +0 -63
  182. package/dist/util/dynamic-element.js +0 -61
  183. package/dist/util/index.js +0 -3
  184. package/dist/util/pop-up-manager.d.ts +0 -186
  185. package/dist/util/pop-up-manager.js +0 -214
  186. /package/{dist/elements/index.d.ts → src/elements/index.ts} +0 -0
  187. /package/{dist/index.d.ts → src/index.ts} +0 -0
  188. /package/{dist/util/index.d.ts → src/util/index.ts} +0 -0
@@ -0,0 +1,380 @@
1
+ import {assert} from '@augment-vir/assert';
2
+ import {type MaybePromise, mapObjectValues} from '@augment-vir/common';
3
+ import {findOverflowAncestor} from '@augment-vir/web';
4
+ import {type Coords, NavActivateEvent, type NavController, NavDirection} from 'device-navigation';
5
+ import {listenToPageActivation} from 'page-active';
6
+ import {
7
+ type ExtractEventByType,
8
+ type ExtractEventTypes,
9
+ type ListenOptions,
10
+ ListenTarget,
11
+ type RemoveListenerCallback,
12
+ defineTypedCustomEvent,
13
+ defineTypedEvent,
14
+ listenToGlobal,
15
+ } from 'typed-event-target';
16
+
17
+ /**
18
+ * Used to prevent pop-ups from closing when a text input is active.
19
+ *
20
+ * @category Internal
21
+ */
22
+ export function isInputLikeElement(element: Element): boolean {
23
+ return (
24
+ (element instanceof HTMLInputElement &&
25
+ (element.type === 'text' ||
26
+ element.type === 'search' ||
27
+ element.type === 'email' ||
28
+ element.type === 'url' ||
29
+ element.type === 'tel' ||
30
+ element.type === 'password' ||
31
+ element.type === 'number')) ||
32
+ element instanceof HTMLTextAreaElement ||
33
+ (element instanceof HTMLElement && element.isContentEditable)
34
+ );
35
+ }
36
+
37
+ /**
38
+ * A type used for representing a rectangle's position.
39
+ *
40
+ * @category Internal
41
+ */
42
+ export type PositionRect = {
43
+ top: number;
44
+ left: number;
45
+ right: number;
46
+ bottom: number;
47
+ };
48
+
49
+ /**
50
+ * The default empty {@link PositionRect}, with all values set to 0.
51
+ *
52
+ * @category Internal
53
+ */
54
+ export const emptyPositionRect: PositionRect = {
55
+ top: 0,
56
+ left: 0,
57
+ right: 0,
58
+ bottom: 0,
59
+ };
60
+
61
+ /**
62
+ * Options for {@link PopUpManager}.
63
+ *
64
+ * @category PopUp
65
+ */
66
+ export type PopUpManagerOptions = {
67
+ /**
68
+ * The minimum number of pixels for allowing the pop-up to go downwards. If the downward
69
+ * available space is less than this, and if the upwards available space is
70
+ * `verticalDiffThreshold` more than the downwards space, the pop-up will be directed upwards.
71
+ *
72
+ * Equation:
73
+ *
74
+ * const directUpwards =
75
+ * downwardsSpace < minDownSpace &&
76
+ * upwardsSpace > DownwardsSpace + verticalDiffThreshold;
77
+ *
78
+ * @default 200
79
+ */
80
+ minDownSpace: number;
81
+ /**
82
+ * The minimum number of pixels for allowing the pop-up to go rightwards. If the rightward
83
+ * available space is less than this, and if the leftwards available space is
84
+ * `horizontalDiffThreshold` more than the rightwards space, the pop-up will be directed
85
+ * leftwards.
86
+ *
87
+ * Equation:
88
+ *
89
+ * const directLeftwards =
90
+ * rightwardsSpace < minRightSpace &&
91
+ * leftwardsSpace > rightwardsSpace + horizontalDiffThreshold;
92
+ *
93
+ * @default 400
94
+ */
95
+ minRightSpace: number;
96
+ /**
97
+ * The number of pixels required for the upwards available space to be bigger than the downwards
98
+ * available space before directing the pop-up upwards.
99
+ *
100
+ * Equation:
101
+ *
102
+ * const directUpwards =
103
+ * downwardsSpace < minDownSpace &&
104
+ * upwardsSpace > DownwardsSpace + verticalDiffThreshold;
105
+ *
106
+ * @default 20
107
+ */
108
+ verticalDiffThreshold: number;
109
+ /**
110
+ * The number of pixels required for the leftwards available space to be bigger than the
111
+ * rightwards available space before directing the pop-up leftwards.
112
+ *
113
+ * Equation:
114
+ *
115
+ * const directLeftwards =
116
+ * rightwardsSpace < minRightSpace &&
117
+ * leftwardsSpace > rightwardsSpace + horizontalDiffThreshold;
118
+ *
119
+ * @default 100
120
+ */
121
+ horizontalDiffThreshold: number;
122
+ /**
123
+ * Supports navigation of the pop up via the `device-navigation` package.
124
+ *
125
+ * @default true
126
+ */
127
+ supportNavigation: boolean;
128
+ };
129
+
130
+ /**
131
+ * Output type from `PopUpManager.showPopUp`
132
+ *
133
+ * @category PopUp
134
+ */
135
+ export type ShowPopUpResult = {
136
+ /**
137
+ * Indicates if the "pop up" should pop in the downwards direction or not. If not, it should pop
138
+ * in the upwards direction. This is determined by how much space is available on either side of
139
+ * the root element.
140
+ */
141
+ popDown: boolean;
142
+ /**
143
+ * Indicates if the "pop up" should pop in the rightwards direction or not. If not, it should
144
+ * pop in the leftwards direction. This is determined by how much space is available on either
145
+ * side of the root element.
146
+ */
147
+ popRight: boolean;
148
+ positions: Record<'root' | 'container' | 'diff', PositionRect>;
149
+ };
150
+
151
+ /**
152
+ * An event fired from {@link PopUpManager} when the pop up should be hidden.
153
+ *
154
+ * @category PopUp
155
+ */
156
+ export class HidePopUpEvent extends defineTypedEvent('hide-pop-up') {}
157
+ /**
158
+ * An event fired from {@link PopUpManager} when an individual item in the pop up has been selected
159
+ * by the user.
160
+ *
161
+ * @category PopUp
162
+ */
163
+ export class NavSelectEvent extends defineTypedCustomEvent<Coords>()('nav-select') {}
164
+
165
+ /**
166
+ * All events that can be emitted by {@link PopUpManager}.
167
+ *
168
+ * @category Internal
169
+ */
170
+ export type PopUpManagerEvents = HidePopUpEvent | NavSelectEvent;
171
+
172
+ /**
173
+ * A "pop up" manager for items that pop up from the HTML page, like dropdowns or menus.
174
+ *
175
+ * @category PopUp
176
+ */
177
+ export class PopUpManager {
178
+ private listenTarget = new ListenTarget<PopUpManagerEvents>();
179
+ public options: PopUpManagerOptions = {
180
+ minDownSpace: 200,
181
+ minRightSpace: 400,
182
+ verticalDiffThreshold: 20,
183
+ horizontalDiffThreshold: 100,
184
+ supportNavigation: true,
185
+ };
186
+ private cleanupCallbacks: (() => void)[] = [];
187
+ private lastRootElement: HTMLElement | undefined;
188
+
189
+ constructor(
190
+ public readonly navController: NavController,
191
+ options?: Partial<PopUpManagerOptions> | undefined,
192
+ ) {
193
+ this.options = {...this.options, ...options};
194
+ }
195
+
196
+ private attachGlobalListeners() {
197
+ this.cleanupCallbacks = [
198
+ listenToPageActivation(false, (isPageActive) => {
199
+ if (!isPageActive) {
200
+ this.removePopUp();
201
+ }
202
+ }),
203
+ this.navController.listen(NavActivateEvent, (event) => {
204
+ const target = event.composedPath()[0];
205
+
206
+ if (target instanceof Element && isInputLikeElement(target)) {
207
+ return;
208
+ }
209
+
210
+ if (event.detail.success) {
211
+ this.listenTarget.dispatch(new NavSelectEvent({detail: event.detail.coords}));
212
+ this.navController.currentNavEntry?.entry.focus(true);
213
+ event.stopImmediatePropagation();
214
+ event.preventDefault();
215
+ }
216
+ }),
217
+ listenToGlobal(
218
+ 'mousedown',
219
+ (event) => {
220
+ if (
221
+ this.lastRootElement &&
222
+ event.composedPath().includes(this.lastRootElement)
223
+ ) {
224
+ /** Ignore clicks that came from the pop up host itself. */
225
+ return;
226
+ }
227
+ this.removePopUp();
228
+ },
229
+ {passive: true},
230
+ ),
231
+ listenToGlobal('keydown', (event) => {
232
+ const keyCode = event.code;
233
+
234
+ if (keyCode === 'Escape') {
235
+ this.removePopUp();
236
+ } else if (this.options.supportNavigation) {
237
+ const target = event.composedPath()[0];
238
+
239
+ if (target instanceof Element && isInputLikeElement(target)) {
240
+ return;
241
+ }
242
+
243
+ if (keyCode === 'ArrowDown') {
244
+ event.stopImmediatePropagation();
245
+ event.preventDefault();
246
+
247
+ this.navController.navigate({
248
+ direction: NavDirection.Down,
249
+ allowWrapping: false,
250
+ });
251
+ } else if (keyCode === 'ArrowUp') {
252
+ event.stopImmediatePropagation();
253
+ event.preventDefault();
254
+
255
+ this.navController.navigate({
256
+ direction: NavDirection.Up,
257
+ allowWrapping: false,
258
+ });
259
+ } else if (keyCode === 'ArrowLeft') {
260
+ event.stopImmediatePropagation();
261
+ event.preventDefault();
262
+
263
+ this.navController.navigate({
264
+ direction: NavDirection.Left,
265
+ allowWrapping: false,
266
+ });
267
+ } else if (keyCode === 'ArrowRight') {
268
+ event.stopImmediatePropagation();
269
+ event.preventDefault();
270
+
271
+ this.navController.navigate({
272
+ direction: NavDirection.Right,
273
+ allowWrapping: false,
274
+ });
275
+ } else if (
276
+ (keyCode === 'Enter' || keyCode === 'Return' || keyCode === 'Space') &&
277
+ this.navController.enterInto({fallbackToActivate: true}).success
278
+ ) {
279
+ event.stopImmediatePropagation();
280
+ event.preventDefault();
281
+ }
282
+ }
283
+ }),
284
+ ];
285
+ }
286
+
287
+ /** Listen to events emitted from a {@link PopUpManager} instance. */
288
+ public listen<
289
+ const EventDefinition extends Readonly<{
290
+ type: ExtractEventTypes<PopUpManagerEvents>;
291
+ }>,
292
+ >(
293
+ event: EventDefinition,
294
+ listener: (
295
+ event: ExtractEventByType<PopUpManagerEvents, EventDefinition['type']>,
296
+ ) => MaybePromise<void>,
297
+ options?: ListenOptions | undefined,
298
+ ): RemoveListenerCallback {
299
+ return this.listenTarget.listen(event, listener, options);
300
+ }
301
+
302
+ /** Trigger removal or hiding of the pop up. */
303
+ public removePopUp() {
304
+ this.cleanupCallbacks.forEach((callback) => callback());
305
+ this.listenTarget.dispatch(new HidePopUpEvent());
306
+ }
307
+
308
+ /** Trigger showing the pop up. */
309
+ public showPopUp(
310
+ rootElement: HTMLElement,
311
+ options?: Partial<PopUpManagerOptions> | undefined,
312
+ ): ShowPopUpResult {
313
+ this.lastRootElement = rootElement;
314
+ const currentOptions = {...this.options, ...options};
315
+ const container = findOverflowAncestor(rootElement);
316
+ assert.instanceOf(container, HTMLElement);
317
+
318
+ const rootRect = rootElement.getBoundingClientRect();
319
+ const containerRect = container.getBoundingClientRect();
320
+
321
+ const containerScrollbarWidth = container.offsetWidth - container.clientWidth;
322
+ const containerScrollbarHeight = container.offsetHeight - container.clientHeight;
323
+
324
+ const containerPosition: PositionRect =
325
+ container === document.body
326
+ ? {
327
+ top: 0,
328
+ left: 0,
329
+ right: containerRect.width,
330
+ bottom: containerRect.height,
331
+ }
332
+ : {
333
+ top: containerRect.top,
334
+ left: containerRect.left,
335
+ right: containerRect.right - containerScrollbarWidth,
336
+ bottom: containerRect.bottom - containerScrollbarHeight,
337
+ };
338
+
339
+ const rootPosition: PositionRect = mapObjectValues(emptyPositionRect, (key) => {
340
+ return rootRect[key];
341
+ });
342
+ const diff: PositionRect = mapObjectValues(emptyPositionRect, (key) => {
343
+ const containerDimension = containerPosition[key];
344
+ const hostDimension = rootPosition[key];
345
+
346
+ return Math.abs(containerDimension - hostDimension);
347
+ });
348
+
349
+ const useUp =
350
+ diff.top > diff.bottom + currentOptions.verticalDiffThreshold &&
351
+ diff.bottom < currentOptions.minDownSpace;
352
+
353
+ const useLeft =
354
+ diff.left > diff.right + currentOptions.horizontalDiffThreshold &&
355
+ diff.right < currentOptions.minRightSpace;
356
+
357
+ this.attachGlobalListeners();
358
+
359
+ return {
360
+ popDown: !useUp,
361
+ popRight: !useLeft,
362
+ positions: {
363
+ container: containerPosition,
364
+ root: rootPosition,
365
+ diff,
366
+ },
367
+ };
368
+ }
369
+
370
+ /**
371
+ * Cleanup and destroy the {@link PopUpManager} instance. This:
372
+ *
373
+ * - Removes the existing pop up
374
+ * - Cleans up all internal and external listeners
375
+ */
376
+ public destroy() {
377
+ this.removePopUp();
378
+ this.listenTarget.destroy();
379
+ }
380
+ }
@@ -1,18 +0,0 @@
1
- /**
2
- * Required prefix for all vira elements.
3
- *
4
- * @category Internal
5
- */
6
- export declare const ViraTagNamePrefix = "vira-";
7
- /**
8
- * Required tag name for all vira elements. This includes {@link ViraTagNamePrefix} in it.
9
- *
10
- * @category Internal
11
- */
12
- export type ViraTagName = `${typeof ViraTagNamePrefix}${string}`;
13
- /**
14
- * Define a vira element with custom requirements (like the `vira-` element tag prefix).
15
- *
16
- * @category Internal
17
- */
18
- export declare const defineViraElement: <Inputs extends {}>(...errorParams: import("element-vir").DeclarativeElementInputErrorParams<Inputs>) => <const TagName extends `vira-${string}`, State extends {}, EventsInit extends {}, const HostClassKeys extends `${TagName}-${string}` = `${TagName}-`, const CssVarKeys extends `${TagName}-${string}` = `${TagName}-`, const SlotNames extends ReadonlyArray<string> = readonly [], const TestIds extends ReadonlyArray<string> = readonly []>(inputs: import("element-vir").DeclarativeElementInit<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames, TestIds>) => import("element-vir").DeclarativeElementDefinition<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames, TestIds>;
@@ -1,19 +0,0 @@
1
- import { wrapDefineElement } from 'element-vir';
2
- /**
3
- * Required prefix for all vira elements.
4
- *
5
- * @category Internal
6
- */
7
- export const ViraTagNamePrefix = `vira-`;
8
- /**
9
- * Define a vira element with custom requirements (like the `vira-` element tag prefix).
10
- *
11
- * @category Internal
12
- */
13
- export const defineViraElement = wrapDefineElement({
14
- assertInputs: (inputs) => {
15
- if (!inputs.tagName.startsWith(ViraTagNamePrefix)) {
16
- throw new Error(`Tag name should start with '${ViraTagNamePrefix}' but got '${inputs.tagName}'`);
17
- }
18
- },
19
- });
@@ -1,100 +0,0 @@
1
- import { type PartialWithUndefined } from '@augment-vir/common';
2
- import { type ViraIconSvg } from '../../icons/icon-svg.js';
3
- import { type ViraSelectOption } from '../vira-select.element.js';
4
- /**
5
- * Form field types for {@link ViraFormField}.
6
- *
7
- * @category Internal
8
- */
9
- export declare enum ViraFormFieldType {
10
- Text = "text",
11
- /** Allows auto complete for _existing_ passwords used on this website (for login). */
12
- ExistingPassword = "existing-password",
13
- /** Allows auto complete for _new_ passwords used on this website (for login). */
14
- NewPassword = "new-password",
15
- /** Uses a password input without any attributes applied for auto complete hints. */
16
- PlainPassword = "plain-password",
17
- Email = "email",
18
- Select = "select",
19
- Checkbox = "checkbox"
20
- }
21
- /**
22
- * {@link ViraFormField} properties that are shared between all field types.
23
- *
24
- * @category Internal
25
- */
26
- export type CommonViraFormFields = {
27
- label: string;
28
- } & PartialWithUndefined<{
29
- /** Applies a test id to the form field element. */
30
- testId: string;
31
- /**
32
- * When `true`, visually indicates the form field as required and affects form validation.
33
- *
34
- * @default false
35
- */
36
- isRequired: boolean;
37
- /**
38
- * When `true`, marks this form field element with error styling.
39
- *
40
- * @default false
41
- */
42
- hasError: boolean;
43
- /**
44
- * When `true`, hides this form field entirely.
45
- *
46
- * @default false
47
- */
48
- isHidden: boolean;
49
- /**
50
- * When `true`, continues showing the form field but prevents edits.
51
- *
52
- * @default false
53
- */
54
- isDisabled: boolean;
55
- }>;
56
- /**
57
- * An individual form field for {@link ViraFormFields}.
58
- *
59
- * @category Internal
60
- */
61
- export type ViraFormField = ({
62
- type: ViraFormFieldType.Text | ViraFormFieldType.ExistingPassword | ViraFormFieldType.NewPassword | ViraFormFieldType.PlainPassword | ViraFormFieldType.Email;
63
- value: string | undefined;
64
- } & PartialWithUndefined<{
65
- placeholder: string;
66
- icon: ViraIconSvg;
67
- isUsername: boolean;
68
- }> & CommonViraFormFields) | ({
69
- type: ViraFormFieldType.Select;
70
- value: string | undefined;
71
- options: ReadonlyArray<Readonly<ViraSelectOption>>;
72
- } & PartialWithUndefined<{
73
- placeholder: string;
74
- icon: ViraIconSvg;
75
- }> & CommonViraFormFields) | ({
76
- type: ViraFormFieldType.Checkbox;
77
- value: boolean | undefined;
78
- } & CommonViraFormFields);
79
- /**
80
- * A collection of form fields for `ViraForm`.
81
- *
82
- * @category Internal
83
- */
84
- export type ViraFormFields = Record<string, ViraFormField>;
85
- /**
86
- * Appends a `'*'` to a label if it exist sand if it is required.
87
- *
88
- * @category Internal
89
- */
90
- export declare function applyRequiredLabel(label: string | undefined, isRequired: boolean): string | undefined;
91
- /**
92
- * Checks if all the {@link ViraFormField} entries in a given {@link ViraFormFields} are valid through
93
- * the following checks:
94
- *
95
- * - Checks that required fields are provided (not `undefined`)
96
- * - Ignores hidden fields
97
- *
98
- * @category Internal
99
- */
100
- export declare function areFormFieldsValid(formFields: Readonly<ViraFormFields>): boolean;
@@ -1,60 +0,0 @@
1
- import { check } from '@augment-vir/assert';
2
- import { addSuffix, getObjectTypedValues } from '@augment-vir/common';
3
- /**
4
- * Form field types for {@link ViraFormField}.
5
- *
6
- * @category Internal
7
- */
8
- export var ViraFormFieldType;
9
- (function (ViraFormFieldType) {
10
- ViraFormFieldType["Text"] = "text";
11
- /** Allows auto complete for _existing_ passwords used on this website (for login). */
12
- ViraFormFieldType["ExistingPassword"] = "existing-password";
13
- /** Allows auto complete for _new_ passwords used on this website (for login). */
14
- ViraFormFieldType["NewPassword"] = "new-password";
15
- /** Uses a password input without any attributes applied for auto complete hints. */
16
- ViraFormFieldType["PlainPassword"] = "plain-password";
17
- ViraFormFieldType["Email"] = "email";
18
- ViraFormFieldType["Select"] = "select";
19
- ViraFormFieldType["Checkbox"] = "checkbox";
20
- })(ViraFormFieldType || (ViraFormFieldType = {}));
21
- /**
22
- * Appends a `'*'` to a label if it exist sand if it is required.
23
- *
24
- * @category Internal
25
- */
26
- export function applyRequiredLabel(label, isRequired) {
27
- if (label) {
28
- if (isRequired) {
29
- return addSuffix({ value: label, suffix: '*' });
30
- }
31
- else {
32
- return label;
33
- }
34
- }
35
- else {
36
- return undefined;
37
- }
38
- }
39
- /**
40
- * Checks if all the {@link ViraFormField} entries in a given {@link ViraFormFields} are valid through
41
- * the following checks:
42
- *
43
- * - Checks that required fields are provided (not `undefined`)
44
- * - Ignores hidden fields
45
- *
46
- * @category Internal
47
- */
48
- export function areFormFieldsValid(formFields) {
49
- return getObjectTypedValues(formFields).every((formField) => {
50
- if (formField.isHidden || !formField.isRequired) {
51
- return true;
52
- }
53
- else if (check.isString(formField.value)) {
54
- return !!formField.value;
55
- }
56
- else {
57
- return formField.value != undefined;
58
- }
59
- });
60
- }
@@ -1,35 +0,0 @@
1
- import { type PartialWithUndefined } from '@augment-vir/common';
2
- import { type ViraFormField, type ViraFormFields } from './vira-form-fields.js';
3
- /**
4
- * A form element.
5
- *
6
- * @category Elements
7
- * @see https://electrovir.github.io/vira/book/elements/vira-form
8
- */
9
- export declare const ViraForm: import("element-vir").DeclarativeElementDefinition<"vira-form", Readonly<{
10
- fields: Readonly<ViraFormFields>;
11
- } & PartialWithUndefined<{
12
- showClearButtons: boolean;
13
- /**
14
- * When `true`, all fields in this form are disabled. Note that this will not (and can
15
- * not) disable any child elements you've inserted via <slot>.
16
- *
17
- * @default false
18
- */
19
- isDisabled: boolean;
20
- /**
21
- * If true, no `'*'` is appended to required form field labels.
22
- *
23
- * @default false
24
- */
25
- hideRequiredMarkers: boolean;
26
- }>>, {
27
- lastIsValid: boolean;
28
- }, {
29
- valueChange: import("element-vir").DefineEvent<{
30
- key: string;
31
- } & ViraFormField>;
32
- validChange: import("element-vir").DefineEvent<{
33
- allFieldsAreValid: boolean;
34
- }>;
35
- }, "vira-form-", "vira-form-", readonly [], readonly []>;