@lmvz-ds/components 0.33.0 → 0.34.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 (159) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/cjs/async.util-BQ60l-WC.js +20 -0
  3. package/cjs/{ds.constants-CKeXfK-s.js → ds.constants-C6eKRAEu.js} +5 -1
  4. package/cjs/{element.util-Cq4y-_iX.js → element.util-Dbyc8yUG.js} +35 -0
  5. package/cjs/index.cjs.js +3 -1
  6. package/cjs/{list-keyboard-controller-StN6Yn8W.js → list-keyboard-controller-Dm5S_l0D.js} +1 -1
  7. package/cjs/lmvz-action-list.cjs.entry.js +11 -4
  8. package/cjs/lmvz-button-group.cjs.entry.js +3 -3
  9. package/cjs/lmvz-button_2.cjs.entry.js +2 -2
  10. package/cjs/lmvz-card.cjs.entry.js +1 -1
  11. package/cjs/lmvz-checkbox.cjs.entry.js +1 -1
  12. package/cjs/lmvz-chip.cjs.entry.js +1 -1
  13. package/cjs/lmvz-components.cjs.js +1 -1
  14. package/cjs/lmvz-header_2.cjs.entry.js +2 -2
  15. package/cjs/lmvz-input.cjs.entry.js +2 -1
  16. package/cjs/lmvz-link.cjs.entry.js +1 -1
  17. package/cjs/lmvz-menuitem.cjs.entry.js +1 -1
  18. package/cjs/lmvz-modal.cjs.entry.js +2 -2
  19. package/cjs/lmvz-popover.cjs.entry.js +1570 -0
  20. package/cjs/lmvz-radio.cjs.entry.js +2 -2
  21. package/cjs/lmvz-select.cjs.entry.js +1 -1
  22. package/cjs/lmvz-snackbar.cjs.entry.js +1 -1
  23. package/cjs/lmvz-spinner.cjs.entry.js +1 -1
  24. package/cjs/lmvz-tab.cjs.entry.js +1 -1
  25. package/cjs/lmvz-tabs.cjs.entry.js +3 -3
  26. package/cjs/lmvz-toggle.cjs.entry.js +4 -3
  27. package/cjs/loader.cjs.js +1 -1
  28. package/cjs/{stencil.util-DzvzXSwk.js → stencil.util-DxdYjVoH.js} +2 -10
  29. package/collection/api/ds.constants.js +3 -1
  30. package/collection/collection-manifest.json +1 -0
  31. package/collection/components/lmvz-action-list/lmvz-action-list.css +150 -38
  32. package/collection/components/lmvz-action-list/lmvz-action-list.js +9 -1
  33. package/collection/components/lmvz-button/lmvz-button.css +14 -18
  34. package/collection/components/lmvz-button/lmvz-button.js +1 -1
  35. package/collection/components/lmvz-button-group/lmvz-button-group.css +1 -2
  36. package/collection/components/lmvz-card/lmvz-card.css +16 -19
  37. package/collection/components/lmvz-checkbox/lmvz-checkbox.css +3 -6
  38. package/collection/components/lmvz-menuitem/lmvz-menuitem.css +1 -2
  39. package/collection/components/lmvz-modal/lmvz-modal.css +1 -2
  40. package/collection/components/lmvz-popover/lmvz-popover.css +46 -0
  41. package/collection/components/lmvz-popover/lmvz-popover.js +470 -0
  42. package/collection/components/lmvz-radio/lmvz-radio.css +2 -4
  43. package/collection/components/lmvz-radio/lmvz-radio.js +1 -1
  44. package/collection/components/lmvz-select/lmvz-select.js +1 -1
  45. package/collection/components/lmvz-snackbar/lmvz-snackbar.js +1 -1
  46. package/collection/components/lmvz-spinner/lmvz-spinner.js +1 -1
  47. package/collection/components/lmvz-tab/lmvz-tab.js +1 -1
  48. package/collection/components/lmvz-tabs/lmvz-tabs.js +1 -1
  49. package/collection/components/lmvz-toggle/lmvz-toggle.css +1 -2
  50. package/collection/components/lmvz-toggle/lmvz-toggle.js +1 -1
  51. package/collection/integration/header-integration/header-integration.js +1 -1
  52. package/collection/utils/async/async.util.js +6 -0
  53. package/collection/utils/element/element.util.js +33 -0
  54. package/components/index.d.ts +2 -0
  55. package/components/index.d.ts.bak +2 -0
  56. package/components/index.js +1 -1
  57. package/components/lmvz-action-list.js +1 -1
  58. package/components/lmvz-button-group.js +1 -1
  59. package/components/lmvz-button.js +1 -1
  60. package/components/lmvz-card.js +1 -1
  61. package/components/lmvz-checkbox.js +1 -1
  62. package/components/lmvz-chip.js +1 -1
  63. package/components/lmvz-header.js +1 -1
  64. package/components/lmvz-input.js +1 -1
  65. package/components/lmvz-link.js +1 -1
  66. package/components/lmvz-menuitem.js +1 -1
  67. package/components/lmvz-message.js +1 -1
  68. package/components/lmvz-modal.js +1 -1
  69. package/components/lmvz-popover.d.ts +11 -0
  70. package/components/lmvz-popover.d.ts.bak +11 -0
  71. package/components/lmvz-popover.js +1 -0
  72. package/components/lmvz-radio.js +1 -1
  73. package/components/lmvz-select.js +1 -1
  74. package/components/lmvz-snackbar.js +1 -1
  75. package/components/lmvz-spinner.js +1 -1
  76. package/components/lmvz-tab.js +1 -1
  77. package/components/lmvz-tabs.js +1 -1
  78. package/components/lmvz-toggle.js +1 -1
  79. package/components/p-0ctLESas.js +1 -0
  80. package/components/p-BhSTYZC6.js +1 -0
  81. package/components/p-CE-QR3Tp.js +1 -0
  82. package/components/{p-CxfT9IA1.js → p-CK3Ixl1K.js} +1 -1
  83. package/components/{p-B4m1n4et.js → p-D-2gj6LP.js} +1 -1
  84. package/components/{p-Rf10bzJY.js → p-D7S1WiEC.js} +1 -1
  85. package/components/p-D9nUtvTm.js +1 -0
  86. package/esm/async.util-D9nUtvTm.js +17 -0
  87. package/esm/{ds.constants-DuEtnKRj.js → ds.constants-0ctLESas.js} +4 -2
  88. package/esm/{element.util-CxfT9IA1.js → element.util-B0eCxdyI.js} +34 -1
  89. package/esm/index.js +1 -1
  90. package/esm/{list-keyboard-controller-BKa9Kd2t.js → list-keyboard-controller-tle6IRkv.js} +1 -1
  91. package/esm/lmvz-action-list.entry.js +11 -4
  92. package/esm/lmvz-button-group.entry.js +3 -3
  93. package/esm/lmvz-button_2.entry.js +2 -2
  94. package/esm/lmvz-card.entry.js +1 -1
  95. package/esm/lmvz-checkbox.entry.js +1 -1
  96. package/esm/lmvz-chip.entry.js +1 -1
  97. package/esm/lmvz-components.js +1 -1
  98. package/esm/lmvz-header_2.entry.js +2 -2
  99. package/esm/lmvz-input.entry.js +2 -1
  100. package/esm/lmvz-link.entry.js +1 -1
  101. package/esm/lmvz-menuitem.entry.js +1 -1
  102. package/esm/lmvz-modal.entry.js +2 -2
  103. package/esm/lmvz-popover.entry.js +1568 -0
  104. package/esm/lmvz-radio.entry.js +2 -2
  105. package/esm/lmvz-select.entry.js +1 -1
  106. package/esm/lmvz-snackbar.entry.js +1 -1
  107. package/esm/lmvz-spinner.entry.js +1 -1
  108. package/esm/lmvz-tab.entry.js +1 -1
  109. package/esm/lmvz-tabs.entry.js +3 -3
  110. package/esm/lmvz-toggle.entry.js +4 -3
  111. package/esm/loader.js +1 -1
  112. package/esm/{stencil.util-CJRqhXjK.js → stencil.util-wGFRYLwZ.js} +1 -9
  113. package/hydrate/index.js +1650 -23
  114. package/hydrate/index.mjs +1650 -23
  115. package/lmvz-components/index.esm.js +1 -1
  116. package/lmvz-components/lmvz-components.esm.js +1 -1
  117. package/lmvz-components/p-03c38ff2.entry.js +1 -0
  118. package/lmvz-components/{p-3a644b99.entry.js → p-08613ba2.entry.js} +1 -1
  119. package/lmvz-components/p-0ctLESas.js +1 -0
  120. package/lmvz-components/{p-00ccaea4.entry.js → p-11de5905.entry.js} +1 -1
  121. package/lmvz-components/{p-b79af711.entry.js → p-2036044c.entry.js} +1 -1
  122. package/lmvz-components/{p-b4aa0978.entry.js → p-4254aa38.entry.js} +1 -1
  123. package/lmvz-components/{p-3da087f4.entry.js → p-49e98627.entry.js} +1 -1
  124. package/lmvz-components/p-4f005b23.entry.js +1 -0
  125. package/lmvz-components/p-50063516.entry.js +1 -0
  126. package/lmvz-components/{p-44781f01.entry.js → p-585470ef.entry.js} +1 -1
  127. package/lmvz-components/{p-24125bcf.entry.js → p-5bbbcfc0.entry.js} +1 -1
  128. package/lmvz-components/p-9b7ce515.entry.js +1 -0
  129. package/lmvz-components/p-9f8fd077.entry.js +1 -0
  130. package/lmvz-components/{p-CxfT9IA1.js → p-B0eCxdyI.js} +1 -1
  131. package/lmvz-components/p-BhSTYZC6.js +1 -0
  132. package/lmvz-components/p-D9nUtvTm.js +1 -0
  133. package/lmvz-components/{p-B4m1n4et.js → p-DuLiExhX.js} +1 -1
  134. package/lmvz-components/{p-47824515.entry.js → p-b0626234.entry.js} +1 -1
  135. package/lmvz-components/{p-48a7b033.entry.js → p-b67ff2d1.entry.js} +1 -1
  136. package/lmvz-components/p-bfde444e.entry.js +1 -0
  137. package/lmvz-components/{p-703b10b5.entry.js → p-cc2734e9.entry.js} +1 -1
  138. package/lmvz-components/{p-25a78ead.entry.js → p-ce1a9f39.entry.js} +1 -1
  139. package/lmvz-components/{p-8be4dbb7.entry.js → p-ddc28256.entry.js} +1 -1
  140. package/lmvz-components/p-fd455288.entry.js +1 -0
  141. package/manifest.json +386 -3
  142. package/package.json +5 -1
  143. package/types/api/ds.constants.d.ts +3 -1
  144. package/types/api/ds.types.d.ts +7 -0
  145. package/types/components/lmvz-popover/lmvz-popover.d.ts +37 -0
  146. package/types/components.d.ts +108 -1
  147. package/types/utils/async/async.util.d.ts +3 -0
  148. package/types/utils/element/element.util.d.ts +2 -0
  149. package/components/p-Bld_XR3X.js +0 -1
  150. package/components/p-CJRqhXjK.js +0 -1
  151. package/components/p-DuEtnKRj.js +0 -1
  152. package/lmvz-components/p-4072b2fb.entry.js +0 -1
  153. package/lmvz-components/p-8c7d9eaf.entry.js +0 -1
  154. package/lmvz-components/p-92d02c56.entry.js +0 -1
  155. package/lmvz-components/p-933e6033.entry.js +0 -1
  156. package/lmvz-components/p-CJRqhXjK.js +0 -1
  157. package/lmvz-components/p-DuEtnKRj.js +0 -1
  158. package/lmvz-components/p-d9619a4f.entry.js +0 -1
  159. package/lmvz-components/p-e1758128.entry.js +0 -1
@@ -80,14 +80,14 @@ hr {
80
80
  --lmvz-button-padding-block: var(--lmvz-button-padding-block-override, var(--lmvz-button-padding, var(--lmvz-component-input-padding-md, clamp(0.88rem, 0.84rem + 0.13vw, 1rem))));
81
81
  --lmvz-button-gap: var(--lmvz-button-gap-override, var(--lmvz-component-input-gap-md, clamp(0.5rem, 0.44rem + 0.26vw, 0.75rem)));
82
82
  --lmvz-button-min-height: var(--lmvz-button-min-height-override, var(--lmvz-component-input-size-md, clamp(2.5rem, 2.44rem + 0.26vw, 2.75rem)));
83
- --lmvz-button-font: var(--lmvz-button-font-override, var(--lmvz-typography-body-md-strong, 500 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
83
+ --lmvz-button-font: var(--lmvz-button-font-override, var(--lmvz-typography-label-md-strong, normal 700 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
84
84
  Router));
85
85
  --lmvz-button-border-width: var(--lmvz-button-border-width-override, 0);
86
86
  --lmvz-button-border-color: var(--lmvz-button-border-color-override, transparent);
87
87
 
88
88
  display: inline-flex;
89
89
  align-items: center;
90
- justify-content: center;
90
+ justify-content: var(--lmvz-button-content-justification-override, center);
91
91
  gap: var(--lmvz-button-gap);
92
92
  padding-block: var(--lmvz-button-padding-block);
93
93
  padding-inline: var(--lmvz-button-padding-inline);
@@ -98,7 +98,7 @@ hr {
98
98
  color: var(--lmvz-button-color);
99
99
  cursor: pointer;
100
100
  font: var(--lmvz-button-font);
101
- text-align: center;
101
+ /* text-align: center; */
102
102
  text-decoration: none;
103
103
  white-space: nowrap;
104
104
  transition:
@@ -155,21 +155,20 @@ button.primary:not([disabled], .disabled):active {
155
155
  --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-primary-active, #545454));
156
156
  }
157
157
 
158
- button.secondary {
159
- --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-secondary, #f0f0f0));
160
- --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-int-on-secondary, #000000));
161
- --lmvz-button-border-width: var(--lmvz-button-border-width-override, 0);
158
+ button.danger {
159
+ --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-tertiary, #ffffff));
162
160
  --lmvz-button-border-color: var(--lmvz-button-border-color-override, transparent);
161
+ --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-status-on-danger, #e52a31));
163
162
  }
164
163
 
165
- button.secondary:not([disabled], .disabled):hover {
166
- --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-secondary-hover, #e0e0e0));
167
- --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-int-on-secondary-hover, #000000));
164
+ button.danger:not([disabled], .disabled):hover {
165
+ --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-status-danger, #fdf1f2));
166
+ --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-status-on-danger, #e52a31));
168
167
  }
169
168
 
170
- button.secondary:not([disabled], .disabled):active {
171
- --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-int-secondary-active, #d4d4d4));
172
- --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-int-on-secondary-active, #000000));
169
+ button.danger:not([disabled], .disabled):active {
170
+ --lmvz-button-background: var(--lmvz-button-background-override, var(--lmvz-semantic-color-status-on-danger-subtle, #f7bfc2));
171
+ --lmvz-button-color: var(--lmvz-button-color-override, var(--lmvz-semantic-color-status-on-danger, #e52a31));
173
172
  }
174
173
 
175
174
  button.tertiary {
@@ -192,7 +191,7 @@ button.small {
192
191
  --lmvz-button-padding-block: var(--lmvz-button-padding-block-override, var(--lmvz-component-input-padding-sm, clamp(0.75rem, 0.72rem + 0.13vw, 0.88rem)));
193
192
  --lmvz-button-gap: var(--lmvz-button-gap-override, var(--lmvz-component-input-gap-sm, clamp(0.38rem, 0.31rem + 0.26vw, 0.63rem)));
194
193
  --lmvz-button-min-height: var(--lmvz-button-min-height-override, var(--lmvz-component-input-size-sm, clamp(2rem, 1.94rem + 0.26vw, 2.25rem)));
195
- --lmvz-button-font: var(--lmvz-button-font-override, var(--lmvz-typography-body-sm-strong, 500 clamp(0.69rem, 0.67rem + 0.06vw, 0.75rem) / 1.5
194
+ --lmvz-button-font: var(--lmvz-button-font-override, var(--lmvz-typography-label-sm-strong, normal 700 clamp(0.69rem, 0.67rem + 0.06vw, 0.75rem) / 1.5
196
195
  Router));
197
196
  }
198
197
 
@@ -201,7 +200,7 @@ button.large {
201
200
  --lmvz-button-padding-block: var(--lmvz-button-padding-block-override, var(--lmvz-component-input-padding-lg, clamp(1rem, 0.94rem + 0.26vw, 1.25rem)));
202
201
  --lmvz-button-gap: var(--lmvz-button-gap-override, var(--lmvz-component-input-gap-lg, clamp(0.75rem, 0.69rem + 0.26vw, 1rem)));
203
202
  --lmvz-button-min-height: var(--lmvz-button-min-height-override, var(--lmvz-component-input-size-lg, clamp(2.75rem, 2.69rem + 0.26vw, 3rem)));
204
- --lmvz-button-font: var(--lmvz-button-font-override, var(--lmvz-typography-body-lg-strong, 500 clamp(1rem, 0.97rem + 0.13vw, 1.13rem) / 1.5
203
+ --lmvz-button-font: var(--lmvz-button-font-override, var(--lmvz-typography-label-lg-strong, normal 700 clamp(1rem, 0.97rem + 0.13vw, 1.13rem) / 1.5
205
204
  Router));
206
205
  }
207
206
 
@@ -218,8 +217,7 @@ button.large {
218
217
  }
219
218
  * {
220
219
  color: var(--lmvz-semantic-color-on-surface-primary, #000000);
221
- font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
222
- Router);
220
+ font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5 Router);
223
221
  }
224
222
  .top {
225
223
  display: flex;
@@ -256,8 +254,7 @@ button.large {
256
254
  align-items: flex-start;
257
255
  align-self: stretch;
258
256
  white-space: pre-line;
259
- font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
260
- Router);
257
+ font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5 Router);
261
258
  }
262
259
  .image-wrapper {
263
260
  aspect-ratio: 4 / 3;
@@ -118,22 +118,19 @@ input {
118
118
  cursor: pointer;
119
119
  }
120
120
  label {
121
- font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
122
- Router);
121
+ font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5 Router);
123
122
  color: var(--checkbox-label-color);
124
123
  transition: color var(--checkbox-duration) var(--checkbox-easing);
125
124
  cursor: pointer;
126
125
  }
127
126
  .helper-text {
128
- font: var(--lmvz-typography-body-sm, 400 clamp(0.69rem, 0.67rem + 0.06vw, 0.75rem) / 1.5
129
- Router);
127
+ font: var(--lmvz-typography-body-sm, 400 clamp(0.69rem, 0.67rem + 0.06vw, 0.75rem) / 1.5 Router);
130
128
  /* font-weight: 400 per DS token standard (body-sm). Note: lmvz-input.css [role='status'] incorrectly uses font-weight: 500 — DS inconsistency, see lmvz-input.css line ~153 */
131
129
  color: var(--checkbox-helper-color);
132
130
  margin-block-start: 2px;
133
131
  }
134
132
  .error-text {
135
- font: var(--lmvz-typography-body-sm, 400 clamp(0.69rem, 0.67rem + 0.06vw, 0.75rem) / 1.5
136
- Router);
133
+ font: var(--lmvz-typography-body-sm, 400 clamp(0.69rem, 0.67rem + 0.06vw, 0.75rem) / 1.5 Router);
137
134
  color: var(--checkbox-error-color);
138
135
  display: block;
139
136
  margin-block-start: 4px;
@@ -44,8 +44,7 @@
44
44
  justify-content: center;
45
45
  gap: var(--lmvz-component-input-md-gap-x, clamp(0.25rem, 0.16rem + 0.39vw, 0.63rem));
46
46
  border-radius: var(--lmvz-semantic-border-radius-lg, 14px);
47
- font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
48
- Router);
47
+ font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5 Router);
49
48
  padding: var(--lmvz-component-input-md-padding-y, clamp(0.75rem, 0.69rem + 0.26vw, 1rem)) var(--lmvz-component-input-md-padding-x, clamp(0.75rem, 0.69rem + 0.26vw, 1rem));
50
49
  cursor: pointer;
51
50
 
@@ -123,8 +123,7 @@ dialog::backdrop {
123
123
  flex: 1 1 auto;
124
124
  }
125
125
  .body {
126
- font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
127
- Router);
126
+ font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5 Router);
128
127
  flex: 1;
129
128
  overflow: scroll;
130
129
  /* min-block-size: clamp(8rem, 40vw, 60vh); */
@@ -0,0 +1,46 @@
1
+
2
+ @layer lmvz-ds.reset, lmvz-ds.theme, lmvz-ds.components, lmvz-ds.overrides;
3
+ /**
4
+ * This defines the order of our lmvz-ds' CSS layers. See readme.md for details.
5
+ * Important: Always import this file _before_ layering your own styles!
6
+ */
7
+ @layer lmvz-ds.components {
8
+ .lmvz-wrapper-card-sm,
9
+ .lmvz-wrapper-card-md,
10
+ .lmvz-wrapper-card-lg {
11
+ background: var(--lmvz-semantic-color-surface-primary, #ffffff);
12
+ box-shadow: var(--lmvz-ds-shadow-l3-default-strong, 0 2px 32px 0 rgba(120, 120, 128, 0.11));
13
+ }
14
+
15
+ .lmvz-wrapper-card-sm {
16
+ padding: var(--lmvz-component-wrapper-sm-padding-y, clamp(0.75rem, 0.69rem + 0.26vw, 1rem)) var(--lmvz-component-wrapper-sm-padding-x, clamp(0.75rem, 0.69rem + 0.26vw, 1rem));
17
+ border-radius: var(--lmvz-component-wrapper-sm-border-radius, 14px);
18
+ }
19
+ .lmvz-wrapper-card-md {
20
+ padding: var(--lmvz-component-wrapper-md-padding-y, clamp(1rem, 0.88rem + 0.52vw, 1.5rem)) var(--lmvz-component-wrapper-md-padding-x, clamp(1rem, 0.88rem + 0.52vw, 1.5rem));
21
+ border-radius: var(--lmvz-component-wrapper-md-border-radius, 18px);
22
+ }
23
+ .lmvz-wrapper-card-lg {
24
+ padding: var(--lmvz-component-wrapper-lg-padding-y, clamp(2.25rem, 2.19rem + 0.26vw, 2.5rem)) var(--lmvz-component-wrapper-lg-padding-x, clamp(1.5rem, 1.14rem + 1.55vw, 3rem));
25
+ border-radius: var(--lmvz-component-wrapper-lg-border-radius, 18px);
26
+ }
27
+
28
+ }
29
+ :host {
30
+ --lmvz-popover-z-index-internal: var(--lmvz-popover-z-index, 1);
31
+ display: contents;
32
+
33
+ .container {
34
+ position: absolute;
35
+ top: -9999999999px;
36
+ left: -9999999999px;
37
+ max-width: var(--lmvz-popover-max-width, none);
38
+ max-height: var(--lmvz-popover-max-height, none);
39
+ z-index: var(--lmvz-popover-z-index-internal);
40
+ overflow: auto;
41
+ box-sizing: border-box;
42
+ }
43
+ }
44
+ :host(:not([open])) .container {
45
+ display: none;
46
+ }
@@ -0,0 +1,470 @@
1
+ import { Host, h } from "@stencil/core";
2
+ import { computePosition, flip, offset, shift } from "@floating-ui/dom";
3
+ import { isAriaValidationEnabled } from "../../utils/aria/aria-validation-controller";
4
+ import { waitFrame } from "../../utils/async/async.util";
5
+ import { canReceiveFocus, getDeepActiveElement, isInteractiveElement, walkShadowDOMUntil } from "../../utils/element/element.util";
6
+ export class LmvzPopover {
7
+ el;
8
+ closureController = new AbortController();
9
+ containerEl;
10
+ slotEl;
11
+ previouslyFocusedElement = null;
12
+ open = false;
13
+ anchor;
14
+ placement = 'bottom-start';
15
+ size = 'sm';
16
+ autoFocus = true;
17
+ label;
18
+ lmvzOpen;
19
+ lmvzClose;
20
+ lmvzCancel;
21
+ async show() {
22
+ this.open = true;
23
+ }
24
+ async hide() {
25
+ this.triggerClose();
26
+ }
27
+ async toggle() {
28
+ if (this.open) {
29
+ await this.hide();
30
+ }
31
+ else {
32
+ await this.show();
33
+ }
34
+ }
35
+ componentDidLoad() {
36
+ autoAssignId(this.el);
37
+ validatePopoverAria(this.el, this.label, this.anchor, this.resolveAnchor());
38
+ }
39
+ handleOpenChange(isOpen) {
40
+ if (isOpen) {
41
+ this.onOpen();
42
+ }
43
+ else {
44
+ this.onClose();
45
+ }
46
+ }
47
+ handleAnchorChange() {
48
+ if (this.open) {
49
+ this.updatePosition();
50
+ }
51
+ }
52
+ disconnectedCallback() {
53
+ this.removeCloseHandlers();
54
+ }
55
+ resolveAnchor() {
56
+ if (!this.anchor)
57
+ return null;
58
+ if (typeof this.anchor === 'string') {
59
+ return document.getElementById(this.anchor);
60
+ }
61
+ return this.anchor;
62
+ }
63
+ async updatePosition() {
64
+ const anchorEl = this.resolveAnchor();
65
+ const container = this.containerEl;
66
+ if (!anchorEl || !container)
67
+ return;
68
+ const placement = toFloatingUiPlacement(this.placement);
69
+ const { x, y } = await computePosition(anchorEl, container, {
70
+ placement,
71
+ middleware: [offset(4), flip(), shift({ padding: 8 })],
72
+ });
73
+ container.style.left = `${x}px`;
74
+ container.style.top = `${y}px`;
75
+ }
76
+ async onOpen() {
77
+ this.previouslyFocusedElement = getDeepActiveElement(document);
78
+ this.setupCloseHandlers();
79
+ console.log('onOpen');
80
+ await waitFrame();
81
+ await this.updatePosition();
82
+ autoAssignId(this.el);
83
+ this.applyAnchorAriaOpen();
84
+ this.lmvzOpen.emit();
85
+ await waitFrame();
86
+ if (this.autoFocus) {
87
+ this.focusFirst();
88
+ }
89
+ }
90
+ onClose() {
91
+ this.removeCloseHandlers();
92
+ this.applyAnchorAriaClose();
93
+ this.restoreFocus();
94
+ this.lmvzClose.emit();
95
+ }
96
+ applyAnchorAriaOpen() {
97
+ const anchorEl = this.resolveAnchor();
98
+ if (!anchorEl)
99
+ return;
100
+ if (!anchorEl.hasAttribute('aria-haspopup')) {
101
+ anchorEl.setAttribute('aria-haspopup', 'dialog');
102
+ }
103
+ anchorEl.setAttribute('aria-expanded', 'true');
104
+ anchorEl.setAttribute('aria-controls', this.el.getAttribute('id'));
105
+ }
106
+ applyAnchorAriaClose() {
107
+ const anchorEl = this.resolveAnchor();
108
+ if (!anchorEl)
109
+ return;
110
+ anchorEl.setAttribute('aria-expanded', 'false');
111
+ }
112
+ focusFirst() {
113
+ const { slotEl } = this;
114
+ if (!slotEl)
115
+ return;
116
+ const assigned = slotEl.assignedElements({ flatten: true });
117
+ for (const el of assigned) {
118
+ const focusable = walkShadowDOMUntil(el, canReceiveFocus);
119
+ if (focusable) {
120
+ focusable.focus();
121
+ return;
122
+ }
123
+ }
124
+ }
125
+ restoreFocus() {
126
+ const el = this.previouslyFocusedElement;
127
+ if (el?.isConnected) {
128
+ el.focus();
129
+ }
130
+ this.previouslyFocusedElement = null;
131
+ }
132
+ triggerClose() {
133
+ const event = this.lmvzCancel.emit();
134
+ if (!event.defaultPrevented) {
135
+ this.open = false;
136
+ }
137
+ }
138
+ setupCloseHandlers() {
139
+ const options = { signal: this.closureController.signal };
140
+ document.addEventListener('mousedown', (event) => {
141
+ if (!this.open)
142
+ return;
143
+ if (this.el.contains(event.target))
144
+ return;
145
+ this.triggerClose();
146
+ }, options);
147
+ document.addEventListener('keydown', (event) => {
148
+ if (!this.open)
149
+ return;
150
+ if (event.key !== 'Escape')
151
+ return;
152
+ this.triggerClose();
153
+ }, options);
154
+ }
155
+ removeCloseHandlers() {
156
+ this.closureController.abort();
157
+ }
158
+ render() {
159
+ return (h(Host, { key: '3dd462a66f17c1617e44787107379d9e4d8ca321' }, h("div", { key: '27106bc8f3169eb07e0d671635074ddb53feb652', role: "dialog", part: "container", class: `container lmvz-wrapper-card-${this.size}`, "aria-label": this.label || undefined, ref: (el) => (this.containerEl = el) }, h("slot", { key: '3401e621d999a225aeb7cb23fa4f5412544a6dab', ref: (el) => (this.slotEl = el) }))));
160
+ }
161
+ static get is() { return "lmvz-popover"; }
162
+ static get encapsulation() { return "shadow"; }
163
+ static get originalStyleUrls() {
164
+ return {
165
+ "$": ["lmvz-popover.css"]
166
+ };
167
+ }
168
+ static get styleUrls() {
169
+ return {
170
+ "$": ["lmvz-popover.css"]
171
+ };
172
+ }
173
+ static get properties() {
174
+ return {
175
+ "open": {
176
+ "type": "boolean",
177
+ "mutable": true,
178
+ "complexType": {
179
+ "original": "boolean",
180
+ "resolved": "boolean",
181
+ "references": {}
182
+ },
183
+ "required": false,
184
+ "optional": false,
185
+ "docs": {
186
+ "tags": [{
187
+ "name": "default",
188
+ "text": "false"
189
+ }],
190
+ "text": "Whether the popover is open."
191
+ },
192
+ "getter": false,
193
+ "setter": false,
194
+ "reflect": true,
195
+ "attribute": "open",
196
+ "defaultValue": "false"
197
+ },
198
+ "anchor": {
199
+ "type": "string",
200
+ "mutable": false,
201
+ "complexType": {
202
+ "original": "string | HTMLElement",
203
+ "resolved": "HTMLElement | string | undefined",
204
+ "references": {
205
+ "HTMLElement": {
206
+ "location": "global",
207
+ "id": "global::HTMLElement"
208
+ }
209
+ }
210
+ },
211
+ "required": false,
212
+ "optional": true,
213
+ "docs": {
214
+ "tags": [],
215
+ "text": "The anchor element or its id. Used for positioning."
216
+ },
217
+ "getter": false,
218
+ "setter": false,
219
+ "reflect": false,
220
+ "attribute": "anchor"
221
+ },
222
+ "placement": {
223
+ "type": "string",
224
+ "mutable": false,
225
+ "complexType": {
226
+ "original": "Popover.Placement",
227
+ "resolved": "\"bottom\" | \"bottom-end\" | \"bottom-start\" | \"end\" | \"start\" | \"top\" | \"top-end\" | \"top-start\"",
228
+ "references": {
229
+ "Popover": {
230
+ "location": "import",
231
+ "path": "../../api",
232
+ "id": "src/api/index.d.ts::Popover",
233
+ "referenceLocation": "Popover"
234
+ }
235
+ }
236
+ },
237
+ "required": false,
238
+ "optional": false,
239
+ "docs": {
240
+ "tags": [{
241
+ "name": "default",
242
+ "text": "'bottom-start'"
243
+ }],
244
+ "text": "Preferred placement relative to the anchor."
245
+ },
246
+ "getter": false,
247
+ "setter": false,
248
+ "reflect": false,
249
+ "attribute": "placement",
250
+ "defaultValue": "'bottom-start'"
251
+ },
252
+ "size": {
253
+ "type": "string",
254
+ "mutable": false,
255
+ "complexType": {
256
+ "original": "Popover.Size",
257
+ "resolved": "\"lg\" | \"md\" | \"sm\"",
258
+ "references": {
259
+ "Popover": {
260
+ "location": "import",
261
+ "path": "../../api",
262
+ "id": "src/api/index.d.ts::Popover",
263
+ "referenceLocation": "Popover"
264
+ }
265
+ }
266
+ },
267
+ "required": false,
268
+ "optional": false,
269
+ "docs": {
270
+ "tags": [{
271
+ "name": "default",
272
+ "text": "'sm'"
273
+ }],
274
+ "text": "Controls the size variant of the card surface."
275
+ },
276
+ "getter": false,
277
+ "setter": false,
278
+ "reflect": false,
279
+ "attribute": "size",
280
+ "defaultValue": "'sm'"
281
+ },
282
+ "autoFocus": {
283
+ "type": "boolean",
284
+ "mutable": false,
285
+ "complexType": {
286
+ "original": "boolean",
287
+ "resolved": "boolean",
288
+ "references": {}
289
+ },
290
+ "required": false,
291
+ "optional": false,
292
+ "docs": {
293
+ "tags": [{
294
+ "name": "default",
295
+ "text": "true"
296
+ }],
297
+ "text": "Whether to move focus to the first focusable element on open."
298
+ },
299
+ "getter": false,
300
+ "setter": false,
301
+ "reflect": false,
302
+ "attribute": "auto-focus",
303
+ "defaultValue": "true"
304
+ },
305
+ "label": {
306
+ "type": "string",
307
+ "mutable": false,
308
+ "complexType": {
309
+ "original": "string",
310
+ "resolved": "string | undefined",
311
+ "references": {}
312
+ },
313
+ "required": false,
314
+ "optional": true,
315
+ "docs": {
316
+ "tags": [],
317
+ "text": "Accessible label for the popover container."
318
+ },
319
+ "getter": false,
320
+ "setter": false,
321
+ "reflect": false,
322
+ "attribute": "label"
323
+ }
324
+ };
325
+ }
326
+ static get events() {
327
+ return [{
328
+ "method": "lmvzOpen",
329
+ "name": "lmvzOpen",
330
+ "bubbles": true,
331
+ "cancelable": true,
332
+ "composed": true,
333
+ "docs": {
334
+ "tags": [],
335
+ "text": "Fired after the popover opens."
336
+ },
337
+ "complexType": {
338
+ "original": "void",
339
+ "resolved": "void",
340
+ "references": {}
341
+ }
342
+ }, {
343
+ "method": "lmvzClose",
344
+ "name": "lmvzClose",
345
+ "bubbles": true,
346
+ "cancelable": true,
347
+ "composed": true,
348
+ "docs": {
349
+ "tags": [],
350
+ "text": "Fired after the popover closes."
351
+ },
352
+ "complexType": {
353
+ "original": "void",
354
+ "resolved": "void",
355
+ "references": {}
356
+ }
357
+ }, {
358
+ "method": "lmvzCancel",
359
+ "name": "lmvzCancel",
360
+ "bubbles": true,
361
+ "cancelable": true,
362
+ "composed": true,
363
+ "docs": {
364
+ "tags": [],
365
+ "text": "Fired before light-dismiss or Escape close.\nCall `event.preventDefault()` to veto the close."
366
+ },
367
+ "complexType": {
368
+ "original": "void",
369
+ "resolved": "void",
370
+ "references": {}
371
+ }
372
+ }];
373
+ }
374
+ static get methods() {
375
+ return {
376
+ "show": {
377
+ "complexType": {
378
+ "signature": "() => Promise<void>",
379
+ "parameters": [],
380
+ "references": {
381
+ "Promise": {
382
+ "location": "global",
383
+ "id": "global::Promise"
384
+ }
385
+ },
386
+ "return": "Promise<void>"
387
+ },
388
+ "docs": {
389
+ "text": "Opens the popover.",
390
+ "tags": []
391
+ }
392
+ },
393
+ "hide": {
394
+ "complexType": {
395
+ "signature": "() => Promise<void>",
396
+ "parameters": [],
397
+ "references": {
398
+ "Promise": {
399
+ "location": "global",
400
+ "id": "global::Promise"
401
+ }
402
+ },
403
+ "return": "Promise<void>"
404
+ },
405
+ "docs": {
406
+ "text": "Closes the popover, firing lmvzCancel first. If cancelled, the popover stays open.",
407
+ "tags": []
408
+ }
409
+ },
410
+ "toggle": {
411
+ "complexType": {
412
+ "signature": "() => Promise<void>",
413
+ "parameters": [],
414
+ "references": {
415
+ "Promise": {
416
+ "location": "global",
417
+ "id": "global::Promise"
418
+ }
419
+ },
420
+ "return": "Promise<void>"
421
+ },
422
+ "docs": {
423
+ "text": "Toggles the popover open state.",
424
+ "tags": []
425
+ }
426
+ }
427
+ };
428
+ }
429
+ static get elementRef() { return "el"; }
430
+ static get watchers() {
431
+ return [{
432
+ "propName": "open",
433
+ "methodName": "handleOpenChange"
434
+ }, {
435
+ "propName": "anchor",
436
+ "methodName": "handleAnchorChange"
437
+ }];
438
+ }
439
+ }
440
+ let popoverIdCounter = 0;
441
+ function autoAssignId(hostEl) {
442
+ if (!hostEl.getAttribute('id')) {
443
+ hostEl.setAttribute('id', `lmvz-popover-${popoverIdCounter++}`);
444
+ }
445
+ }
446
+ function toFloatingUiPlacement(placement) {
447
+ if (placement === 'start')
448
+ return 'left';
449
+ if (placement === 'end')
450
+ return 'right';
451
+ return placement;
452
+ }
453
+ function validatePopoverAria(hostEl, label, anchorProp, anchorEl) {
454
+ if (!isAriaValidationEnabled())
455
+ return;
456
+ const hasAriaLabel = !!label;
457
+ const hasAriaLabelledBy = hostEl.hasAttribute('aria-labelledby');
458
+ if (!hasAriaLabel && !hasAriaLabelledBy) {
459
+ console.warn('[lmvz-popover] Host element has no accessible label. Provide a `label` prop or an `aria-labelledby` attribute pointing to a valid element.');
460
+ }
461
+ if (!anchorProp)
462
+ return;
463
+ if (!anchorEl) {
464
+ console.warn('[lmvz-popover] Anchor prop is set but resolved to null. Ensure the anchor element exists in the DOM when the component loads.');
465
+ return;
466
+ }
467
+ if (!isInteractiveElement(anchorEl)) {
468
+ console.warn('[lmvz-popover] Anchor element is not interactive. Ensure the anchor is a button, link, input, select, textarea, has a `tabindex` attribute, or has an ARIA role that implies interactivity (button, link, menuitem, option, combobox, listbox, checkbox, radio, switch, tab).');
469
+ }
470
+ }
@@ -110,16 +110,14 @@ input {
110
110
  min-width: 0;
111
111
  }
112
112
  label {
113
- font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5
114
- Router);
113
+ font: var(--lmvz-typography-body-md, 400 clamp(0.88rem, 0.84rem + 0.13vw, 1rem) / 1.5 Router);
115
114
  color: var(--radio-label-color);
116
115
  cursor: pointer;
117
116
  transition: color var(--radio-duration) var(--radio-easing);
118
117
  }
119
118
  .helper-text {
120
119
  display: block;
121
- font: var(--lmvz-typography-body-sm, 400 clamp(0.69rem, 0.67rem + 0.06vw, 0.75rem) / 1.5
122
- Router);
120
+ font: var(--lmvz-typography-body-sm, 400 clamp(0.69rem, 0.67rem + 0.06vw, 0.75rem) / 1.5 Router);
123
121
  color: var(--radio-helper-color);
124
122
  margin-block-start: 2px;
125
123
  }