luxen-ui 0.21.1 → 0.21.3
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.
- package/cdn/custom-elements.json +214 -214
- package/cdn/elements/avatar/avatar.js +1 -1
- package/cdn/elements/avatar/avatar.js.map +1 -1
- package/cdn/elements/combobox/combobox.js +1 -1
- package/cdn/elements/combobox/combobox.js.map +1 -1
- package/cdn/elements/dialog/dialog.styles.js +1 -1
- package/cdn/elements/dialog/dialog.styles.js.map +1 -1
- package/cdn/elements/dropdown-label/dropdown-label.js +1 -1
- package/cdn/elements/dropdown-label/dropdown-label.js.map +1 -1
- package/cdn/elements/select/select.js +1 -1
- package/cdn/elements/select/select.js.map +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.js +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.js.map +1 -1
- package/cdn/elements/tabs/tabs.d.ts +33 -0
- package/cdn/elements/tabs/tabs.d.ts.map +1 -1
- package/cdn/elements/tabs/tabs.js +1 -1
- package/cdn/elements/tabs/tabs.js.map +1 -1
- package/cdn/standalone.css +9 -9
- package/cdn/styles/elements/disclosure.css +1 -1
- package/cdn/styles/elements/divider.css +1 -1
- package/cdn/styles/elements/kbd.css +1 -1
- package/cdn/styles/elements/prose-editor.css +1 -1
- package/cdn/styles/elements/segmented-control.css +1 -1
- package/cdn/styles/elements/select.css +1 -1
- package/cdn/styles/elements/story.css +1 -1
- package/cdn/styles/elements/tabs/enclosed.css +1 -1
- package/cdn/styles/elements/tabs/line.css +1 -1
- package/dist/css/elements/disclosure.css +1 -1
- package/dist/css/elements/divider.css +1 -1
- package/dist/css/elements/kbd.css +1 -1
- package/dist/css/elements/prose-editor.css +1 -1
- package/dist/css/elements/segmented-control.css +1 -1
- package/dist/css/elements/select.css +1 -1
- package/dist/css/elements/story.css +1 -1
- package/dist/css/elements/tabs/enclosed.css +1 -1
- package/dist/css/elements/tabs/line.css +1 -1
- package/dist/custom-elements.json +214 -214
- package/dist/elements/avatar/avatar.css +2 -2
- package/dist/elements/combobox/combobox.css +1 -1
- package/dist/elements/dialog/dialog.css +1 -1
- package/dist/elements/dropdown-label/dropdown-label.css +1 -1
- package/dist/elements/select/select.css +2 -2
- package/dist/elements/stories-viewer/stories-viewer.css +1 -1
- package/dist/elements/tabs/tabs.d.ts +33 -0
- package/dist/elements/tabs/tabs.d.ts.map +1 -1
- package/dist/elements/tabs/tabs.js +249 -1
- package/dist/metadata/index.json +1 -1
- package/dist/templates/elements/tabs.md +45 -2
- package/package.json +1 -1
package/cdn/custom-elements.json
CHANGED
|
@@ -172,6 +172,181 @@
|
|
|
172
172
|
}
|
|
173
173
|
]
|
|
174
174
|
},
|
|
175
|
+
{
|
|
176
|
+
"kind": "javascript-module",
|
|
177
|
+
"path": "src/html/elements/avatar/avatar.ts",
|
|
178
|
+
"declarations": [
|
|
179
|
+
{
|
|
180
|
+
"kind": "class",
|
|
181
|
+
"description": "",
|
|
182
|
+
"name": "Avatar",
|
|
183
|
+
"cssProperties": [
|
|
184
|
+
{
|
|
185
|
+
"description": "Box size (any length). Set it inline (e.g. `style=\"--size: 20px\"`) for an arbitrary size beyond the `size` token scale; the font then follows proportionally. The `size` attribute sets it to the matching token.",
|
|
186
|
+
"name": "--size",
|
|
187
|
+
"default": "40px"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"description": "Background fill color for initials and the default icon.",
|
|
191
|
+
"name": "--color"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"description": "Initials/icon color over `--color`. Defaults to an auto-derived readable color; set it to enforce a specific brand color (overrides the automatic choice).",
|
|
195
|
+
"name": "--text-color"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"description": "Set to `circle` for a fully circular avatar (default is a rounded square).",
|
|
199
|
+
"name": "--appearance"
|
|
200
|
+
}
|
|
201
|
+
],
|
|
202
|
+
"cssParts": [
|
|
203
|
+
{
|
|
204
|
+
"description": "The avatar container that paints `--color`; style it (e.g. `color`) to override the auto-derived text color.",
|
|
205
|
+
"name": "base"
|
|
206
|
+
}
|
|
207
|
+
],
|
|
208
|
+
"members": [
|
|
209
|
+
{
|
|
210
|
+
"kind": "field",
|
|
211
|
+
"name": "src",
|
|
212
|
+
"type": {
|
|
213
|
+
"text": "string"
|
|
214
|
+
},
|
|
215
|
+
"default": "''",
|
|
216
|
+
"description": "Image URL. Falls back to initials (then the default icon) if it fails to load.",
|
|
217
|
+
"attribute": "src"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"kind": "field",
|
|
221
|
+
"name": "name",
|
|
222
|
+
"type": {
|
|
223
|
+
"text": "string"
|
|
224
|
+
},
|
|
225
|
+
"default": "''",
|
|
226
|
+
"description": "Name used as the accessible label and to derive the initials fallback.",
|
|
227
|
+
"attribute": "name"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"kind": "field",
|
|
231
|
+
"name": "size",
|
|
232
|
+
"type": {
|
|
233
|
+
"text": "string"
|
|
234
|
+
},
|
|
235
|
+
"default": "'md'",
|
|
236
|
+
"description": "Avatar size: `xs`, `sm`, `md` (default), `lg`, or `xl`.",
|
|
237
|
+
"attribute": "size",
|
|
238
|
+
"reflects": true
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"kind": "field",
|
|
242
|
+
"name": "badge",
|
|
243
|
+
"type": {
|
|
244
|
+
"text": "number"
|
|
245
|
+
},
|
|
246
|
+
"default": "0",
|
|
247
|
+
"description": "Count shown in the corner badge. `0` hides the badge.",
|
|
248
|
+
"attribute": "badge"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"kind": "field",
|
|
252
|
+
"name": "interactive",
|
|
253
|
+
"type": {
|
|
254
|
+
"text": "boolean"
|
|
255
|
+
},
|
|
256
|
+
"default": "false",
|
|
257
|
+
"description": "Render as a `<button>` with focus ring and hover states.",
|
|
258
|
+
"attribute": "interactive",
|
|
259
|
+
"reflects": true
|
|
260
|
+
}
|
|
261
|
+
],
|
|
262
|
+
"attributes": [
|
|
263
|
+
{
|
|
264
|
+
"name": "src",
|
|
265
|
+
"type": {
|
|
266
|
+
"text": "string"
|
|
267
|
+
},
|
|
268
|
+
"default": "''",
|
|
269
|
+
"description": "Image URL. Falls back to initials (then the default icon) if it fails to load.",
|
|
270
|
+
"fieldName": "src"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"name": "name",
|
|
274
|
+
"type": {
|
|
275
|
+
"text": "string"
|
|
276
|
+
},
|
|
277
|
+
"default": "''",
|
|
278
|
+
"description": "Name used as the accessible label and to derive the initials fallback.",
|
|
279
|
+
"fieldName": "name"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"name": "size",
|
|
283
|
+
"type": {
|
|
284
|
+
"text": "string"
|
|
285
|
+
},
|
|
286
|
+
"default": "'md'",
|
|
287
|
+
"description": "Avatar size: `xs`, `sm`, `md` (default), `lg`, or `xl`.",
|
|
288
|
+
"fieldName": "size"
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"name": "badge",
|
|
292
|
+
"type": {
|
|
293
|
+
"text": "number"
|
|
294
|
+
},
|
|
295
|
+
"default": "0",
|
|
296
|
+
"description": "Count shown in the corner badge. `0` hides the badge.",
|
|
297
|
+
"fieldName": "badge"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"name": "interactive",
|
|
301
|
+
"type": {
|
|
302
|
+
"text": "boolean"
|
|
303
|
+
},
|
|
304
|
+
"default": "false",
|
|
305
|
+
"description": "Render as a `<button>` with focus ring and hover states.",
|
|
306
|
+
"fieldName": "interactive"
|
|
307
|
+
}
|
|
308
|
+
],
|
|
309
|
+
"superclass": {
|
|
310
|
+
"name": "LuxenElement",
|
|
311
|
+
"module": "/src/html/shared/luxen-element.js"
|
|
312
|
+
},
|
|
313
|
+
"tagName": "l-avatar",
|
|
314
|
+
"customElement": true,
|
|
315
|
+
"summary": "An avatar component for displaying user images, initials, or a default icon.",
|
|
316
|
+
"_cssClasses": [
|
|
317
|
+
{
|
|
318
|
+
"name": ".l-avatar-group",
|
|
319
|
+
"description": "Flex wrapper that overlaps a row of stacked avatars."
|
|
320
|
+
}
|
|
321
|
+
]
|
|
322
|
+
}
|
|
323
|
+
],
|
|
324
|
+
"exports": [
|
|
325
|
+
{
|
|
326
|
+
"kind": "js",
|
|
327
|
+
"name": "Avatar",
|
|
328
|
+
"declaration": {
|
|
329
|
+
"name": "Avatar",
|
|
330
|
+
"module": "src/html/elements/avatar/avatar.ts"
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"kind": "javascript-module",
|
|
337
|
+
"path": "src/html/elements/avatar/index.ts",
|
|
338
|
+
"declarations": [],
|
|
339
|
+
"exports": [
|
|
340
|
+
{
|
|
341
|
+
"kind": "js",
|
|
342
|
+
"name": "*",
|
|
343
|
+
"declaration": {
|
|
344
|
+
"name": "*",
|
|
345
|
+
"module": "src/html/elements/avatar/avatar.js"
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
},
|
|
175
350
|
{
|
|
176
351
|
"kind": "javascript-module",
|
|
177
352
|
"path": "src/html/elements/alert-dialog/alert-dialog.ts",
|
|
@@ -652,181 +827,6 @@
|
|
|
652
827
|
}
|
|
653
828
|
]
|
|
654
829
|
},
|
|
655
|
-
{
|
|
656
|
-
"kind": "javascript-module",
|
|
657
|
-
"path": "src/html/elements/avatar/avatar.ts",
|
|
658
|
-
"declarations": [
|
|
659
|
-
{
|
|
660
|
-
"kind": "class",
|
|
661
|
-
"description": "",
|
|
662
|
-
"name": "Avatar",
|
|
663
|
-
"cssProperties": [
|
|
664
|
-
{
|
|
665
|
-
"description": "Box size (any length). Set it inline (e.g. `style=\"--size: 20px\"`) for an arbitrary size beyond the `size` token scale; the font then follows proportionally. The `size` attribute sets it to the matching token.",
|
|
666
|
-
"name": "--size",
|
|
667
|
-
"default": "40px"
|
|
668
|
-
},
|
|
669
|
-
{
|
|
670
|
-
"description": "Background fill color for initials and the default icon.",
|
|
671
|
-
"name": "--color"
|
|
672
|
-
},
|
|
673
|
-
{
|
|
674
|
-
"description": "Initials/icon color over `--color`. Defaults to an auto-derived readable color; set it to enforce a specific brand color (overrides the automatic choice).",
|
|
675
|
-
"name": "--text-color"
|
|
676
|
-
},
|
|
677
|
-
{
|
|
678
|
-
"description": "Set to `circle` for a fully circular avatar (default is a rounded square).",
|
|
679
|
-
"name": "--appearance"
|
|
680
|
-
}
|
|
681
|
-
],
|
|
682
|
-
"cssParts": [
|
|
683
|
-
{
|
|
684
|
-
"description": "The avatar container that paints `--color`; style it (e.g. `color`) to override the auto-derived text color.",
|
|
685
|
-
"name": "base"
|
|
686
|
-
}
|
|
687
|
-
],
|
|
688
|
-
"members": [
|
|
689
|
-
{
|
|
690
|
-
"kind": "field",
|
|
691
|
-
"name": "src",
|
|
692
|
-
"type": {
|
|
693
|
-
"text": "string"
|
|
694
|
-
},
|
|
695
|
-
"default": "''",
|
|
696
|
-
"description": "Image URL. Falls back to initials (then the default icon) if it fails to load.",
|
|
697
|
-
"attribute": "src"
|
|
698
|
-
},
|
|
699
|
-
{
|
|
700
|
-
"kind": "field",
|
|
701
|
-
"name": "name",
|
|
702
|
-
"type": {
|
|
703
|
-
"text": "string"
|
|
704
|
-
},
|
|
705
|
-
"default": "''",
|
|
706
|
-
"description": "Name used as the accessible label and to derive the initials fallback.",
|
|
707
|
-
"attribute": "name"
|
|
708
|
-
},
|
|
709
|
-
{
|
|
710
|
-
"kind": "field",
|
|
711
|
-
"name": "size",
|
|
712
|
-
"type": {
|
|
713
|
-
"text": "string"
|
|
714
|
-
},
|
|
715
|
-
"default": "'md'",
|
|
716
|
-
"description": "Avatar size: `xs`, `sm`, `md` (default), `lg`, or `xl`.",
|
|
717
|
-
"attribute": "size",
|
|
718
|
-
"reflects": true
|
|
719
|
-
},
|
|
720
|
-
{
|
|
721
|
-
"kind": "field",
|
|
722
|
-
"name": "badge",
|
|
723
|
-
"type": {
|
|
724
|
-
"text": "number"
|
|
725
|
-
},
|
|
726
|
-
"default": "0",
|
|
727
|
-
"description": "Count shown in the corner badge. `0` hides the badge.",
|
|
728
|
-
"attribute": "badge"
|
|
729
|
-
},
|
|
730
|
-
{
|
|
731
|
-
"kind": "field",
|
|
732
|
-
"name": "interactive",
|
|
733
|
-
"type": {
|
|
734
|
-
"text": "boolean"
|
|
735
|
-
},
|
|
736
|
-
"default": "false",
|
|
737
|
-
"description": "Render as a `<button>` with focus ring and hover states.",
|
|
738
|
-
"attribute": "interactive",
|
|
739
|
-
"reflects": true
|
|
740
|
-
}
|
|
741
|
-
],
|
|
742
|
-
"attributes": [
|
|
743
|
-
{
|
|
744
|
-
"name": "src",
|
|
745
|
-
"type": {
|
|
746
|
-
"text": "string"
|
|
747
|
-
},
|
|
748
|
-
"default": "''",
|
|
749
|
-
"description": "Image URL. Falls back to initials (then the default icon) if it fails to load.",
|
|
750
|
-
"fieldName": "src"
|
|
751
|
-
},
|
|
752
|
-
{
|
|
753
|
-
"name": "name",
|
|
754
|
-
"type": {
|
|
755
|
-
"text": "string"
|
|
756
|
-
},
|
|
757
|
-
"default": "''",
|
|
758
|
-
"description": "Name used as the accessible label and to derive the initials fallback.",
|
|
759
|
-
"fieldName": "name"
|
|
760
|
-
},
|
|
761
|
-
{
|
|
762
|
-
"name": "size",
|
|
763
|
-
"type": {
|
|
764
|
-
"text": "string"
|
|
765
|
-
},
|
|
766
|
-
"default": "'md'",
|
|
767
|
-
"description": "Avatar size: `xs`, `sm`, `md` (default), `lg`, or `xl`.",
|
|
768
|
-
"fieldName": "size"
|
|
769
|
-
},
|
|
770
|
-
{
|
|
771
|
-
"name": "badge",
|
|
772
|
-
"type": {
|
|
773
|
-
"text": "number"
|
|
774
|
-
},
|
|
775
|
-
"default": "0",
|
|
776
|
-
"description": "Count shown in the corner badge. `0` hides the badge.",
|
|
777
|
-
"fieldName": "badge"
|
|
778
|
-
},
|
|
779
|
-
{
|
|
780
|
-
"name": "interactive",
|
|
781
|
-
"type": {
|
|
782
|
-
"text": "boolean"
|
|
783
|
-
},
|
|
784
|
-
"default": "false",
|
|
785
|
-
"description": "Render as a `<button>` with focus ring and hover states.",
|
|
786
|
-
"fieldName": "interactive"
|
|
787
|
-
}
|
|
788
|
-
],
|
|
789
|
-
"superclass": {
|
|
790
|
-
"name": "LuxenElement",
|
|
791
|
-
"module": "/src/html/shared/luxen-element.js"
|
|
792
|
-
},
|
|
793
|
-
"tagName": "l-avatar",
|
|
794
|
-
"customElement": true,
|
|
795
|
-
"summary": "An avatar component for displaying user images, initials, or a default icon.",
|
|
796
|
-
"_cssClasses": [
|
|
797
|
-
{
|
|
798
|
-
"name": ".l-avatar-group",
|
|
799
|
-
"description": "Flex wrapper that overlaps a row of stacked avatars."
|
|
800
|
-
}
|
|
801
|
-
]
|
|
802
|
-
}
|
|
803
|
-
],
|
|
804
|
-
"exports": [
|
|
805
|
-
{
|
|
806
|
-
"kind": "js",
|
|
807
|
-
"name": "Avatar",
|
|
808
|
-
"declaration": {
|
|
809
|
-
"name": "Avatar",
|
|
810
|
-
"module": "src/html/elements/avatar/avatar.ts"
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
]
|
|
814
|
-
},
|
|
815
|
-
{
|
|
816
|
-
"kind": "javascript-module",
|
|
817
|
-
"path": "src/html/elements/avatar/index.ts",
|
|
818
|
-
"declarations": [],
|
|
819
|
-
"exports": [
|
|
820
|
-
{
|
|
821
|
-
"kind": "js",
|
|
822
|
-
"name": "*",
|
|
823
|
-
"declaration": {
|
|
824
|
-
"name": "*",
|
|
825
|
-
"module": "src/html/elements/avatar/avatar.js"
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
]
|
|
829
|
-
},
|
|
830
830
|
{
|
|
831
831
|
"kind": "javascript-module",
|
|
832
832
|
"path": "src/html/elements/badge/badge.ts",
|
|
@@ -4796,6 +4796,45 @@
|
|
|
4796
4796
|
}
|
|
4797
4797
|
]
|
|
4798
4798
|
},
|
|
4799
|
+
{
|
|
4800
|
+
"kind": "javascript-module",
|
|
4801
|
+
"path": "src/html/elements/kbd/kbd.meta.ts",
|
|
4802
|
+
"declarations": [
|
|
4803
|
+
{
|
|
4804
|
+
"kind": "class",
|
|
4805
|
+
"description": "",
|
|
4806
|
+
"name": "KbdMeta",
|
|
4807
|
+
"summary": "Displays keyboard keys or shortcuts inline with text.",
|
|
4808
|
+
"examples": [
|
|
4809
|
+
{
|
|
4810
|
+
"title": "Single key",
|
|
4811
|
+
"language": "html",
|
|
4812
|
+
"code": "<kbd class=\"l-kbd\">Esc</kbd>"
|
|
4813
|
+
}
|
|
4814
|
+
],
|
|
4815
|
+
"_cssClasses": [
|
|
4816
|
+
{
|
|
4817
|
+
"name": ".l-kbd",
|
|
4818
|
+
"description": "Base class for keyboard key styling on `<kbd>` elements."
|
|
4819
|
+
}
|
|
4820
|
+
],
|
|
4821
|
+
"customElement": false,
|
|
4822
|
+
"_native": true,
|
|
4823
|
+
"_nativeTag": "kbd",
|
|
4824
|
+
"selector": ".l-kbd"
|
|
4825
|
+
}
|
|
4826
|
+
],
|
|
4827
|
+
"exports": [
|
|
4828
|
+
{
|
|
4829
|
+
"kind": "js",
|
|
4830
|
+
"name": "KbdMeta",
|
|
4831
|
+
"declaration": {
|
|
4832
|
+
"name": "KbdMeta",
|
|
4833
|
+
"module": "src/html/elements/kbd/kbd.meta.ts"
|
|
4834
|
+
}
|
|
4835
|
+
}
|
|
4836
|
+
]
|
|
4837
|
+
},
|
|
4799
4838
|
{
|
|
4800
4839
|
"kind": "javascript-module",
|
|
4801
4840
|
"path": "src/html/elements/input-stepper/index.ts",
|
|
@@ -5032,45 +5071,6 @@
|
|
|
5032
5071
|
}
|
|
5033
5072
|
]
|
|
5034
5073
|
},
|
|
5035
|
-
{
|
|
5036
|
-
"kind": "javascript-module",
|
|
5037
|
-
"path": "src/html/elements/kbd/kbd.meta.ts",
|
|
5038
|
-
"declarations": [
|
|
5039
|
-
{
|
|
5040
|
-
"kind": "class",
|
|
5041
|
-
"description": "",
|
|
5042
|
-
"name": "KbdMeta",
|
|
5043
|
-
"summary": "Displays keyboard keys or shortcuts inline with text.",
|
|
5044
|
-
"examples": [
|
|
5045
|
-
{
|
|
5046
|
-
"title": "Single key",
|
|
5047
|
-
"language": "html",
|
|
5048
|
-
"code": "<kbd class=\"l-kbd\">Esc</kbd>"
|
|
5049
|
-
}
|
|
5050
|
-
],
|
|
5051
|
-
"_cssClasses": [
|
|
5052
|
-
{
|
|
5053
|
-
"name": ".l-kbd",
|
|
5054
|
-
"description": "Base class for keyboard key styling on `<kbd>` elements."
|
|
5055
|
-
}
|
|
5056
|
-
],
|
|
5057
|
-
"customElement": false,
|
|
5058
|
-
"_native": true,
|
|
5059
|
-
"_nativeTag": "kbd",
|
|
5060
|
-
"selector": ".l-kbd"
|
|
5061
|
-
}
|
|
5062
|
-
],
|
|
5063
|
-
"exports": [
|
|
5064
|
-
{
|
|
5065
|
-
"kind": "js",
|
|
5066
|
-
"name": "KbdMeta",
|
|
5067
|
-
"declaration": {
|
|
5068
|
-
"name": "KbdMeta",
|
|
5069
|
-
"module": "src/html/elements/kbd/kbd.meta.ts"
|
|
5070
|
-
}
|
|
5071
|
-
}
|
|
5072
|
-
]
|
|
5073
|
-
},
|
|
5074
5074
|
{
|
|
5075
5075
|
"kind": "javascript-module",
|
|
5076
5076
|
"path": "src/html/elements/popover/index.ts",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e}from"../../chunks/lit.js";import{i as t,r as n,t as r}from"../../chunks/decorate.js";import{a as i,o as a,t as o}from"../../chunks/lit-html.js";import{LuxenElement as s}from"../../shared/luxen-element.js";import{r as c,t as l}from"../../chunks/static-html.js";import u from"../../shared/styles/host.styles.js";var d=e(`:host{--size:40px;--_font-size:calc(var(--size) * .4);width:var(--size);height:var(--size);border-radius:calc(var(--size) * .15);isolation:isolate;vertical-align:middle;color:var(--l-color-text-secondary);flex-shrink:0;justify-content:center;align-items:center;display:inline-flex;position:relative}:host([size=xs]){--size:24px;--_font-size:.75rem}:host([size=sm]){--size:32px;--_font-size:.875rem}:host([size=lg]){--size:48px;--_font-size:1.25rem}:host([size=xl]){--size:56px;--_font-size:1.25rem}img{object-fit:cover;border-radius:inherit;width:100%;height:100%}.initials{margin:auto}.icon{color:currentColor;width:60%;height:60%}.badge{z-index:1;min-width:12px;height:12px;box-shadow:0 0 0 2px var(--l-color-surface);background-color:var(--l-color-surface);font-variant-numeric:tabular-nums;color:var(--l-color-text-primary);border-radius:3px;justify-content:center;align-items:center;padding-inline:2px;
|
|
1
|
+
import{i as e}from"../../chunks/lit.js";import{i as t,r as n,t as r}from"../../chunks/decorate.js";import{a as i,o as a,t as o}from"../../chunks/lit-html.js";import{LuxenElement as s}from"../../shared/luxen-element.js";import{r as c,t as l}from"../../chunks/static-html.js";import u from"../../shared/styles/host.styles.js";var d=e(`:host{--size:40px;--_font-size:calc(var(--size) * .4);width:var(--size);height:var(--size);border-radius:calc(var(--size) * .15);isolation:isolate;vertical-align:middle;color:var(--l-color-text-secondary);flex-shrink:0;justify-content:center;align-items:center;display:inline-flex;position:relative}:host([size=xs]){--size:24px;--_font-size:.75rem}:host([size=sm]){--size:32px;--_font-size:.875rem}:host([size=lg]){--size:48px;--_font-size:1.25rem}:host([size=xl]){--size:56px;--_font-size:1.25rem}img{object-fit:cover;border-radius:inherit;width:100%;height:100%}.initials{margin:auto}.icon{color:currentColor;width:60%;height:60%}.badge{z-index:1;min-width:12px;height:12px;box-shadow:0 0 0 2px var(--l-color-surface);background-color:var(--l-color-surface);font-size:.625rem;font-weight:var(--l-font-weight-medium);font-variant-numeric:tabular-nums;color:var(--l-color-text-primary);border-radius:3px;justify-content:center;align-items:center;padding-inline:2px;line-height:1;display:flex;position:absolute;bottom:0;right:0;overflow:hidden}.base:after{content:"";border-radius:inherit;pointer-events:none;position:absolute;inset:0;box-shadow:inset 0 0 0 1px var(--lightningcss-light,oklch(0% 0 0/.07))var(--lightningcss-dark,oklch(100% 0 0/.1))}.base{border-radius:calc(var(--size) * .15);background-color:var(--color,var(--l-color-bg-fill-neutral-soft));--_on:calc(255 * ( 1 - sign(.2126 * (r / 255) * (r / 255) + .7152 * (g / 255) * (g / 255) + .0722 * (b / 255) * (b / 255) - .2) ) / 2);width:100%;height:100%;color:var(--text-color,rgb(from var(--color) var(--_on) var(--_on) var(--_on)));font-size:var(--_font-size);font-weight:var(--l-font-weight-medium);text-transform:uppercase;cursor:inherit;border:none;justify-content:center;align-items:center;padding:0;line-height:1;display:inline-flex}@supports (color:contrast-color(red)){.base{color:var(--text-color,contrast-color(var(--color)))}}button.base{cursor:pointer}button.base:focus-visible{outline:2px solid var(--l-focus-ring);outline-offset:2px}button.base:hover{box-shadow:inset 0 0 0 1.5px var(--l-color-border-interactive)}@container style(--appearance:circle){.base{border-radius:50%}}`);function f(e=``){let t=e.normalize(`NFC`).trim().split(/\s+/).filter(Boolean);if(t.length===0)return``;let n=e=>[...e][0];return(n(t[0])+(t.length>1?n(t[t.length-1]):``)).toUpperCase()}var p=a`<svg class="icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
2
2
|
<path d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z" />
|
|
3
3
|
</svg>`,m=class extends s{constructor(...e){super(...e),this.src=``,this.name=``,this.size=`md`,this.badge=0,this.interactive=!1,this._hasError=!1,this._onError=()=>{this._hasError=!0}}static{this.styles=[u,d]}willUpdate(e){e.has(`src`)&&(this._hasError=!1)}connectedCallback(){super.connectedCallback(),!this.interactive&&!this.hasAttribute(`role`)&&this.setAttribute(`role`,`img`)}updated(){this.interactive?(this.getAttribute(`role`)===`img`&&this.removeAttribute(`role`),this.removeAttribute(`aria-label`)):(this.hasAttribute(`role`)||this.setAttribute(`role`,`img`),this.name&&this.setAttribute(`aria-label`,this.name));let e=getComputedStyle(this).getPropertyValue(`--appearance`).trim()===`circle`;this.style.borderRadius=e?`50%`:``}get _tag(){return this.interactive?l`button`:l`div`}render(){let e=this.src&&!this._hasError?i`<img
|
|
4
4
|
src=${this.src}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar.js","names":[],"sources":["../../../src/html/elements/avatar/avatar.css?inline","../../../src/html/elements/avatar/avatar.ts"],"sourcesContent":[":host {\n --size: 40px;\n --_font-size: calc(var(--size) * 0.4);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n width: var(--size);\n height: var(--size);\n border-radius: calc(var(--size) * 0.15);\n isolation: isolate;\n vertical-align: middle;\n flex-shrink: 0;\n color: var(--l-color-text-secondary);\n}\n\n:host([size='xs']) {\n --size: 24px;\n --_font-size: 0.75rem;\n}\n:host([size='sm']) {\n --size: 32px;\n --_font-size: 0.875rem;\n}\n:host([size='lg']) {\n --size: 48px;\n --_font-size: 1.25rem;\n}\n:host([size='xl']) {\n --size: 56px;\n --_font-size: 1.25rem;\n}\n\nimg {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: inherit;\n}\n\n.initials {\n margin: auto;\n}\n\n.icon {\n width: 60%;\n height: 60%;\n color: currentColor;\n}\n\n.badge {\n position: absolute;\n bottom: 0;\n right: 0;\n z-index: 1;\n height: 12px;\n min-width: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding-inline: 2px;\n border-radius: 3px;\n box-shadow: 0 0 0 2px var(--l-color-surface);\n background-color: var(--l-color-surface);\n font-size: 0.625rem;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n line-height: 1;\n color: var(--l-color-text-primary);\n overflow: hidden;\n}\n\n/*\n * Inset ring via ::after so it renders on top of the <img>.\n * A box-shadow on :host would be covered by the image since\n * it fills the entire element with object-fit: cover.\n */\n.base::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n box-shadow: inset 0 0 0 1px light-dark(oklch(0 0 0 / 7%), oklch(100% 0 0 / 10%));\n pointer-events: none;\n}\n\n.base {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n border: none;\n border-radius: calc(var(--size) * 0.15);\n background-color: var(--color, var(--l-color-bg-fill-neutral-soft));\n /*\n * Text over --color, decided by the background's own luminance — never the\n * document mode, since --color is consumer-set and ignores light/dark.\n * The contrast-color() block below is the primary path (Baseline 2026); this\n * --_on calc() is the fallback for browsers predating it (Chrome ≤146,\n * Safari <26, Firefox <146). It approximates WCAG relative luminance with\n * squared sRGB channels (a cheap linearization, Rec. 709 weights) and flips at\n * 0.2, just above the black/white crossover (~0.179) to offset squaring\n * underestimating mid-tones — holding AA across saturated brand colors where an\n * OKLCH-lightness threshold collapses to ≈1:1 (OKLCH L tracks hue, not\n * luminance: a mid red reads \"light\" yet needs white text). --text-color lets\n * consumers force a specific brand text color, overriding both paths.\n */\n --_on: calc(\n 255 *\n (\n 1 -\n sign(\n 0.2126 * (r / 255) * (r / 255) + 0.7152 * (g / 255) * (g / 255) + 0.0722 * (b / 255) *\n (b / 255) - 0.2\n )\n ) /\n 2\n );\n color: var(--text-color, rgb(from var(--color) var(--_on) var(--_on) var(--_on)));\n font-size: var(--_font-size);\n font-weight: 500;\n line-height: 1;\n text-transform: uppercase;\n padding: 0;\n cursor: inherit;\n}\n\n/* Primary path: native, guaranteed-contrast black/white. contrast-color() is\n * Baseline Newly Available (2026) — Safari 26+, Firefox 146+, Chrome/Edge 147+ —\n * and supersedes the luminance approximation above where supported. @supports (not\n * declaration order) is required: the value contains var(), so a non-supporting\n * browser would treat contrast-color() as invalid-at-computed-value-time and reset\n * to `inherit` rather than falling back to the calc() line. No bg fallback inside,\n * so a bare avatar (no --color) keeps inheriting --l-color-text-secondary.\n * --text-color still wins here, overriding contrast-color()'s choice.\n * (The earlier `… vs black, white to AA` extended syntax was dropped from the spec.) */\n@supports (color: contrast-color(red)) {\n .base {\n color: var(--text-color, contrast-color(var(--color)));\n }\n}\n\nbutton.base {\n cursor: pointer;\n}\n\nbutton.base:focus-visible {\n outline: 2px solid var(--l-focus-ring);\n outline-offset: 2px;\n}\n\nbutton.base:hover {\n box-shadow: inset 0 0 0 1.5px var(--l-color-border-interactive);\n}\n\n@container style(--appearance: circle) {\n .base {\n border-radius: 50%;\n }\n}\n","import { html, nothing, svg, unsafeCSS } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { html as staticHtml, literal } from 'lit/static-html.js';\nimport { property, state } from 'lit/decorators.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './avatar.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * Extracts up to two uppercase initials from a name: the first letter of the\n * first word, plus the first letter of the last word when there is more than one.\n *\n * Splits on whitespace rather than relying on a `\\b`/`\\w` regex, which only\n * recognises ASCII and mangles accented or non-ASCII names.\n *\n * @param name - The name to extract initials from. Defaults to an empty string.\n * @return The uppercased initials, or an empty string when `name` is blank.\n *\n * @example getInitials('John Doe') // 'JD'\n * @example getInitials('Markus Nösterer') // 'MN' (accents preserved)\n * @example getInitials('Cher') // 'C' (single word → one initial)\n * @example getInitials(' John Doe ') // 'JD' (extra whitespace ignored)\n * @example getInitials('') // ''\n */\nfunction getInitials(name: string = ''): string {\n const words = name.normalize('NFC').trim().split(/\\s+/).filter(Boolean);\n if (words.length === 0) return '';\n\n // Spreading iterates by code point, so an accented letter (or an astral\n // character like an emoji) is taken whole instead of a broken half.\n // oxlint-disable-next-line typescript/no-misused-spread -- code-point-safe first char is the intent\n const firstLetter = (word: string) => [...word][0];\n\n const first = firstLetter(words[0]);\n const last = words.length > 1 ? firstLetter(words[words.length - 1]) : '';\n return (first + last).toUpperCase();\n}\n\nconst defaultIcon = svg`<svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z\" />\n</svg>`;\n\n/**\n * @summary An avatar component for displaying user images, initials, or a default icon.\n * @customElement l-avatar\n *\n * @cssproperty [--size=40px] - Box size (any length). Set it inline (e.g. `style=\"--size: 20px\"`) for an arbitrary size beyond the `size` token scale; the font then follows proportionally. The `size` attribute sets it to the matching token.\n * @cssproperty --color - Background fill color for initials and the default icon.\n * @cssproperty --text-color - Initials/icon color over `--color`. Defaults to an auto-derived readable color; set it to enforce a specific brand color (overrides the automatic choice).\n * @cssproperty --appearance - Set to `circle` for a fully circular avatar (default is a rounded square).\n *\n * @csspart base - The avatar container that paints `--color`; style it (e.g. `color`) to override the auto-derived text color.\n *\n * @cssClass .l-avatar-group - Flex wrapper that overlaps a row of stacked avatars.\n */\nexport class Avatar extends LuxenElement {\n static styles = [hostStyles, styles];\n\n /** Image URL. Falls back to initials (then the default icon) if it fails to load. */\n @property()\n src = '';\n\n /** Name used as the accessible label and to derive the initials fallback. */\n @property()\n name = '';\n\n /** Avatar size: `xs`, `sm`, `md` (default), `lg`, or `xl`. */\n @property({ reflect: true })\n size = 'md';\n\n /** Count shown in the corner badge. `0` hides the badge. */\n @property({ type: Number })\n badge = 0;\n\n /** Render as a `<button>` with focus ring and hover states. */\n @property({ type: Boolean, reflect: true })\n interactive = false;\n\n @state() private _hasError = false;\n\n willUpdate(changed: Map<string, unknown>) {\n if (changed.has('src')) {\n this._hasError = false;\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n if (!this.interactive && !this.hasAttribute('role')) {\n this.setAttribute('role', 'img');\n }\n }\n\n updated() {\n // An interactive avatar renders a focusable <button>, and a role=\"img\" node\n // must stay a leaf in the accessibility tree — so the host carries no role\n // or label and the inner button holds the accessible name (see render()).\n if (this.interactive) {\n if (this.getAttribute('role') === 'img') this.removeAttribute('role');\n this.removeAttribute('aria-label');\n } else {\n if (!this.hasAttribute('role')) this.setAttribute('role', 'img');\n if (this.name) this.setAttribute('aria-label', this.name);\n }\n\n const isCircle = getComputedStyle(this).getPropertyValue('--appearance').trim() === 'circle';\n this.style.borderRadius = isCircle ? '50%' : '';\n }\n\n private get _tag() {\n return this.interactive ? literal`button` : literal`div`;\n }\n\n render() {\n const content =\n this.src && !this._hasError\n ? html`<img\n src=${this.src}\n alt=${this.name || ''}\n @error=${this._onError}\n />`\n : this.name\n ? html`<span class=\"initials\">${getInitials(this.name)}</span>`\n : html`<slot>${defaultIcon}</slot>`;\n\n return staticHtml`\n <${this._tag}\n class=\"base\"\n part=\"base\"\n type=${this.interactive ? 'button' : nothing}\n aria-label=${this.interactive && this.name ? this.name : nothing}\n >\n ${content}\n </${this._tag}>\n ${\n this.badge\n ? html`<div\n class=\"badge\"\n aria-hidden=\"true\"\n >\n ${this.badge}\n </div>`\n : nothing\n }\n `;\n }\n\n private _onError = () => {\n this._hasError = true;\n };\n}\n"],"mappings":"oUCOA,IAAM,EAAS,EAAU,4jEAAS,EAkBlC,SAAS,EAAY,EAAe,GAAY,CAC9C,IAAM,EAAQ,EAAK,UAAU,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO,EACtE,GAAI,EAAM,SAAW,EAAG,MAAO,GAK/B,IAAM,EAAe,GAAiB,CAAC,GAAG,CAAI,CAAC,CAAC,GAIhD,OAFc,EAAY,EAAM,EAExB,GADK,EAAM,OAAS,EAAI,EAAY,EAAM,EAAM,OAAS,EAAE,EAAI,IAAA,CACjD,YAAY,CACpC,CAEA,IAAM,EAAc,CAAG;;QAiBV,EAAb,cAA4B,CAAa,wCAKjC,aAIC,aAIA,gBAIC,mBAIM,kBAEe,qBAqEJ,CACvB,KAAK,UAAY,EACnB,qBA7FgB,CAAC,EAAY,CAAM,EAwBnC,WAAW,EAA+B,CACpC,EAAQ,IAAI,KAAK,IACnB,KAAK,UAAY,GAErB,CAEA,mBAAoB,CAClB,MAAM,kBAAkB,EACpB,CAAC,KAAK,aAAe,CAAC,KAAK,aAAa,MAAM,GAChD,KAAK,aAAa,OAAQ,KAAK,CAEnC,CAEA,SAAU,CAIJ,KAAK,aACH,KAAK,aAAa,MAAM,IAAM,OAAO,KAAK,gBAAgB,MAAM,EACpE,KAAK,gBAAgB,YAAY,IAE5B,KAAK,aAAa,MAAM,GAAG,KAAK,aAAa,OAAQ,KAAK,EAC3D,KAAK,MAAM,KAAK,aAAa,aAAc,KAAK,IAAI,GAG1D,IAAM,EAAW,iBAAiB,IAAI,CAAC,CAAC,iBAAiB,cAAc,CAAC,CAAC,KAAK,IAAM,SACpF,KAAK,MAAM,aAAe,EAAW,MAAQ,EAC/C,CAEA,IAAY,MAAO,CACjB,OAAO,KAAK,YAAc,CAAO,SAAW,CAAO,KACrD,CAEA,QAAS,CACP,IAAM,EACJ,KAAK,KAAO,CAAC,KAAK,UACd,CAAI;kBACI,KAAK,IAAI;kBACT,KAAK,MAAQ,GAAG;qBACb,KAAK,SAAS;cAEzB,KAAK,KACH,CAAI,0BAA0B,EAAY,KAAK,IAAI,EAAE,SACrD,CAAI,SAAS,EAAY,SAEjC,MAAO,EAAU;SACZ,KAAK,KAAK;;;eAGJ,KAAK,YAAc,SAAW,EAAQ;qBAChC,KAAK,aAAe,KAAK,KAAO,KAAK,KAAO,EAAQ;;UAE/D,EAAQ;UACR,KAAK,KAAK;QAEZ,KAAK,MACD,CAAI;;;;gBAIA,KAAK,MAAM;oBAEf,EACL;KAEL,CAKF,KA3FG,EAAS,CAAA,EAAA,EAAA,UAAA,MAAA,IAAA,EAAA,KAIT,EAAS,CAAA,EAAA,EAAA,UAAA,OAAA,IAAA,EAAA,KAIT,EAAS,CAAE,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,OAAA,IAAA,EAAA,KAI1B,EAAS,CAAE,KAAM,MAAO,CAAC,CAAA,EAAA,EAAA,UAAA,QAAA,IAAA,EAAA,KAIzB,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,cAAA,IAAA,EAAA,KAGzC,EAAM,CAAA,EAAA,EAAA,UAAA,YAAA,IAAA,EAAA"}
|
|
1
|
+
{"version":3,"file":"avatar.js","names":[],"sources":["../../../src/html/elements/avatar/avatar.css?inline","../../../src/html/elements/avatar/avatar.ts"],"sourcesContent":[":host {\n --size: 40px;\n --_font-size: calc(var(--size) * 0.4);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n width: var(--size);\n height: var(--size);\n border-radius: calc(var(--size) * 0.15);\n isolation: isolate;\n vertical-align: middle;\n flex-shrink: 0;\n color: var(--l-color-text-secondary);\n}\n\n:host([size='xs']) {\n --size: 24px;\n --_font-size: 0.75rem;\n}\n:host([size='sm']) {\n --size: 32px;\n --_font-size: 0.875rem;\n}\n:host([size='lg']) {\n --size: 48px;\n --_font-size: 1.25rem;\n}\n:host([size='xl']) {\n --size: 56px;\n --_font-size: 1.25rem;\n}\n\nimg {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: inherit;\n}\n\n.initials {\n margin: auto;\n}\n\n.icon {\n width: 60%;\n height: 60%;\n color: currentColor;\n}\n\n.badge {\n position: absolute;\n bottom: 0;\n right: 0;\n z-index: 1;\n height: 12px;\n min-width: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding-inline: 2px;\n border-radius: 3px;\n box-shadow: 0 0 0 2px var(--l-color-surface);\n background-color: var(--l-color-surface);\n font-size: 0.625rem;\n font-weight: var(--l-font-weight-medium);\n font-variant-numeric: tabular-nums;\n line-height: 1;\n color: var(--l-color-text-primary);\n overflow: hidden;\n}\n\n/*\n * Inset ring via ::after so it renders on top of the <img>.\n * A box-shadow on :host would be covered by the image since\n * it fills the entire element with object-fit: cover.\n */\n.base::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n box-shadow: inset 0 0 0 1px light-dark(oklch(0 0 0 / 7%), oklch(100% 0 0 / 10%));\n pointer-events: none;\n}\n\n.base {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n border: none;\n border-radius: calc(var(--size) * 0.15);\n background-color: var(--color, var(--l-color-bg-fill-neutral-soft));\n /*\n * Text over --color, decided by the background's own luminance — never the\n * document mode, since --color is consumer-set and ignores light/dark.\n * The contrast-color() block below is the primary path (Baseline 2026); this\n * --_on calc() is the fallback for browsers predating it (Chrome ≤146,\n * Safari <26, Firefox <146). It approximates WCAG relative luminance with\n * squared sRGB channels (a cheap linearization, Rec. 709 weights) and flips at\n * 0.2, just above the black/white crossover (~0.179) to offset squaring\n * underestimating mid-tones — holding AA across saturated brand colors where an\n * OKLCH-lightness threshold collapses to ≈1:1 (OKLCH L tracks hue, not\n * luminance: a mid red reads \"light\" yet needs white text). --text-color lets\n * consumers force a specific brand text color, overriding both paths.\n */\n --_on: calc(\n 255 *\n (\n 1 -\n sign(\n 0.2126 * (r / 255) * (r / 255) + 0.7152 * (g / 255) * (g / 255) + 0.0722 * (b / 255) *\n (b / 255) - 0.2\n )\n ) /\n 2\n );\n color: var(--text-color, rgb(from var(--color) var(--_on) var(--_on) var(--_on)));\n font-size: var(--_font-size);\n font-weight: var(--l-font-weight-medium);\n line-height: 1;\n text-transform: uppercase;\n padding: 0;\n cursor: inherit;\n}\n\n/* Primary path: native, guaranteed-contrast black/white. contrast-color() is\n * Baseline Newly Available (2026) — Safari 26+, Firefox 146+, Chrome/Edge 147+ —\n * and supersedes the luminance approximation above where supported. @supports (not\n * declaration order) is required: the value contains var(), so a non-supporting\n * browser would treat contrast-color() as invalid-at-computed-value-time and reset\n * to `inherit` rather than falling back to the calc() line. No bg fallback inside,\n * so a bare avatar (no --color) keeps inheriting --l-color-text-secondary.\n * --text-color still wins here, overriding contrast-color()'s choice.\n * (The earlier `… vs black, white to AA` extended syntax was dropped from the spec.) */\n@supports (color: contrast-color(red)) {\n .base {\n color: var(--text-color, contrast-color(var(--color)));\n }\n}\n\nbutton.base {\n cursor: pointer;\n}\n\nbutton.base:focus-visible {\n outline: 2px solid var(--l-focus-ring);\n outline-offset: 2px;\n}\n\nbutton.base:hover {\n box-shadow: inset 0 0 0 1.5px var(--l-color-border-interactive);\n}\n\n@container style(--appearance: circle) {\n .base {\n border-radius: 50%;\n }\n}\n","import { html, nothing, svg, unsafeCSS } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { html as staticHtml, literal } from 'lit/static-html.js';\nimport { property, state } from 'lit/decorators.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './avatar.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * Extracts up to two uppercase initials from a name: the first letter of the\n * first word, plus the first letter of the last word when there is more than one.\n *\n * Splits on whitespace rather than relying on a `\\b`/`\\w` regex, which only\n * recognises ASCII and mangles accented or non-ASCII names.\n *\n * @param name - The name to extract initials from. Defaults to an empty string.\n * @return The uppercased initials, or an empty string when `name` is blank.\n *\n * @example getInitials('John Doe') // 'JD'\n * @example getInitials('Markus Nösterer') // 'MN' (accents preserved)\n * @example getInitials('Cher') // 'C' (single word → one initial)\n * @example getInitials(' John Doe ') // 'JD' (extra whitespace ignored)\n * @example getInitials('') // ''\n */\nfunction getInitials(name: string = ''): string {\n const words = name.normalize('NFC').trim().split(/\\s+/).filter(Boolean);\n if (words.length === 0) return '';\n\n // Spreading iterates by code point, so an accented letter (or an astral\n // character like an emoji) is taken whole instead of a broken half.\n // oxlint-disable-next-line typescript/no-misused-spread -- code-point-safe first char is the intent\n const firstLetter = (word: string) => [...word][0];\n\n const first = firstLetter(words[0]);\n const last = words.length > 1 ? firstLetter(words[words.length - 1]) : '';\n return (first + last).toUpperCase();\n}\n\nconst defaultIcon = svg`<svg class=\"icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z\" />\n</svg>`;\n\n/**\n * @summary An avatar component for displaying user images, initials, or a default icon.\n * @customElement l-avatar\n *\n * @cssproperty [--size=40px] - Box size (any length). Set it inline (e.g. `style=\"--size: 20px\"`) for an arbitrary size beyond the `size` token scale; the font then follows proportionally. The `size` attribute sets it to the matching token.\n * @cssproperty --color - Background fill color for initials and the default icon.\n * @cssproperty --text-color - Initials/icon color over `--color`. Defaults to an auto-derived readable color; set it to enforce a specific brand color (overrides the automatic choice).\n * @cssproperty --appearance - Set to `circle` for a fully circular avatar (default is a rounded square).\n *\n * @csspart base - The avatar container that paints `--color`; style it (e.g. `color`) to override the auto-derived text color.\n *\n * @cssClass .l-avatar-group - Flex wrapper that overlaps a row of stacked avatars.\n */\nexport class Avatar extends LuxenElement {\n static styles = [hostStyles, styles];\n\n /** Image URL. Falls back to initials (then the default icon) if it fails to load. */\n @property()\n src = '';\n\n /** Name used as the accessible label and to derive the initials fallback. */\n @property()\n name = '';\n\n /** Avatar size: `xs`, `sm`, `md` (default), `lg`, or `xl`. */\n @property({ reflect: true })\n size = 'md';\n\n /** Count shown in the corner badge. `0` hides the badge. */\n @property({ type: Number })\n badge = 0;\n\n /** Render as a `<button>` with focus ring and hover states. */\n @property({ type: Boolean, reflect: true })\n interactive = false;\n\n @state() private _hasError = false;\n\n willUpdate(changed: Map<string, unknown>) {\n if (changed.has('src')) {\n this._hasError = false;\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n if (!this.interactive && !this.hasAttribute('role')) {\n this.setAttribute('role', 'img');\n }\n }\n\n updated() {\n // An interactive avatar renders a focusable <button>, and a role=\"img\" node\n // must stay a leaf in the accessibility tree — so the host carries no role\n // or label and the inner button holds the accessible name (see render()).\n if (this.interactive) {\n if (this.getAttribute('role') === 'img') this.removeAttribute('role');\n this.removeAttribute('aria-label');\n } else {\n if (!this.hasAttribute('role')) this.setAttribute('role', 'img');\n if (this.name) this.setAttribute('aria-label', this.name);\n }\n\n const isCircle = getComputedStyle(this).getPropertyValue('--appearance').trim() === 'circle';\n this.style.borderRadius = isCircle ? '50%' : '';\n }\n\n private get _tag() {\n return this.interactive ? literal`button` : literal`div`;\n }\n\n render() {\n const content =\n this.src && !this._hasError\n ? html`<img\n src=${this.src}\n alt=${this.name || ''}\n @error=${this._onError}\n />`\n : this.name\n ? html`<span class=\"initials\">${getInitials(this.name)}</span>`\n : html`<slot>${defaultIcon}</slot>`;\n\n return staticHtml`\n <${this._tag}\n class=\"base\"\n part=\"base\"\n type=${this.interactive ? 'button' : nothing}\n aria-label=${this.interactive && this.name ? this.name : nothing}\n >\n ${content}\n </${this._tag}>\n ${\n this.badge\n ? html`<div\n class=\"badge\"\n aria-hidden=\"true\"\n >\n ${this.badge}\n </div>`\n : nothing\n }\n `;\n }\n\n private _onError = () => {\n this._hasError = true;\n };\n}\n"],"mappings":"oUCOA,IAAM,EAAS,EAAU,4mEAAS,EAkBlC,SAAS,EAAY,EAAe,GAAY,CAC9C,IAAM,EAAQ,EAAK,UAAU,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO,EACtE,GAAI,EAAM,SAAW,EAAG,MAAO,GAK/B,IAAM,EAAe,GAAiB,CAAC,GAAG,CAAI,CAAC,CAAC,GAIhD,OAFc,EAAY,EAAM,EAExB,GADK,EAAM,OAAS,EAAI,EAAY,EAAM,EAAM,OAAS,EAAE,EAAI,IAAA,CACjD,YAAY,CACpC,CAEA,IAAM,EAAc,CAAG;;QAiBV,EAAb,cAA4B,CAAa,wCAKjC,aAIC,aAIA,gBAIC,mBAIM,kBAEe,qBAqEJ,CACvB,KAAK,UAAY,EACnB,qBA7FgB,CAAC,EAAY,CAAM,EAwBnC,WAAW,EAA+B,CACpC,EAAQ,IAAI,KAAK,IACnB,KAAK,UAAY,GAErB,CAEA,mBAAoB,CAClB,MAAM,kBAAkB,EACpB,CAAC,KAAK,aAAe,CAAC,KAAK,aAAa,MAAM,GAChD,KAAK,aAAa,OAAQ,KAAK,CAEnC,CAEA,SAAU,CAIJ,KAAK,aACH,KAAK,aAAa,MAAM,IAAM,OAAO,KAAK,gBAAgB,MAAM,EACpE,KAAK,gBAAgB,YAAY,IAE5B,KAAK,aAAa,MAAM,GAAG,KAAK,aAAa,OAAQ,KAAK,EAC3D,KAAK,MAAM,KAAK,aAAa,aAAc,KAAK,IAAI,GAG1D,IAAM,EAAW,iBAAiB,IAAI,CAAC,CAAC,iBAAiB,cAAc,CAAC,CAAC,KAAK,IAAM,SACpF,KAAK,MAAM,aAAe,EAAW,MAAQ,EAC/C,CAEA,IAAY,MAAO,CACjB,OAAO,KAAK,YAAc,CAAO,SAAW,CAAO,KACrD,CAEA,QAAS,CACP,IAAM,EACJ,KAAK,KAAO,CAAC,KAAK,UACd,CAAI;kBACI,KAAK,IAAI;kBACT,KAAK,MAAQ,GAAG;qBACb,KAAK,SAAS;cAEzB,KAAK,KACH,CAAI,0BAA0B,EAAY,KAAK,IAAI,EAAE,SACrD,CAAI,SAAS,EAAY,SAEjC,MAAO,EAAU;SACZ,KAAK,KAAK;;;eAGJ,KAAK,YAAc,SAAW,EAAQ;qBAChC,KAAK,aAAe,KAAK,KAAO,KAAK,KAAO,EAAQ;;UAE/D,EAAQ;UACR,KAAK,KAAK;QAEZ,KAAK,MACD,CAAI;;;;gBAIA,KAAK,MAAM;oBAEf,EACL;KAEL,CAKF,KA3FG,EAAS,CAAA,EAAA,EAAA,UAAA,MAAA,IAAA,EAAA,KAIT,EAAS,CAAA,EAAA,EAAA,UAAA,OAAA,IAAA,EAAA,KAIT,EAAS,CAAE,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,OAAA,IAAA,EAAA,KAI1B,EAAS,CAAE,KAAM,MAAO,CAAC,CAAA,EAAA,EAAA,UAAA,QAAA,IAAA,EAAA,KAIzB,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAA,EAAA,UAAA,cAAA,IAAA,EAAA,KAGzC,EAAM,CAAA,EAAA,EAAA,UAAA,YAAA,IAAA,EAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{cls as e,uniqueId as t}from"../../registry.js";import{i as n}from"../../chunks/lit.js";import{i as r,r as i,t as a}from"../../chunks/decorate.js";import{a as o,t as s}from"../../chunks/lit-html.js";import{LocalizeController as c}from"../../shared/localize.js";import l from"../../shared/styles/host.styles.js";import{t as u}from"../../chunks/unsafe-html.js";import{LuxenFormAssociatedElement as d}from"../../shared/luxen-form-associated-element.js";import{PopoverController as f}from"../../shared/controllers/popover.js";import{ListboxNavController as p}from"../../shared/controllers/listbox-nav.js";var m=n(`:host{--height:var(--l-form-control-height);--border-radius:var(--l-form-control-border-radius);--background:var(--l-color-surface-overlay);inline-size:100%;display:block}:host([size=xs]){--height:var(--l-size-control-xs)}:host([size=sm]){--height:var(--l-size-control-sm)}:host([size=lg]){--height:var(--l-size-control-lg)}:host([size=xl]){--height:var(--l-size-control-xl)}:host([disabled]){opacity:.5;pointer-events:none}.base{position:relative}.control{block-size:var(--height);padding-inline:var(--l-form-control-padding-inline);border:var(--l-form-control-border-width) solid var(--l-form-control-border-color);border-radius:var(--border-radius);background-color:var(--l-form-control-background-color);cursor:text;align-items:center;gap:.25rem;display:flex}@media (hover:hover){.control:hover{border-color:var(--l-form-control-border-color-hover)}}.control:has(.input:focus-visible){border-color:var(--l-focus-ring);box-shadow:0 0 0 3px color-mix(in oklab, var(--l-focus-ring) 22%, transparent)}.input{min-inline-size:0;color:var(--l-form-control-value-color);font:inherit;background:0 0;border:0;outline:none;flex:1}.input::placeholder{color:var(--l-form-control-placeholder-color)}.chevron{block-size:1em;inline-size:1em;color:var(--l-form-control-placeholder-color);-webkit-mask:var(--_chevron-icon) center / contain no-repeat;mask:var(--_chevron-icon) center / contain no-repeat;background-color:currentColor;flex:none;transition:rotate .15s}.clear{cursor:pointer;block-size:1.5rem;inline-size:1.5rem;color:var(--l-form-control-placeholder-color);-webkit-mask:var(--_x-icon) center / 1em no-repeat;mask:var(--_x-icon) center / 1em no-repeat;background-color:currentColor;border:0;flex:none;padding:0}@media (hover:hover){.clear:hover{color:var(--l-form-control-value-color)}}.control:has(.input[aria-expanded=true]) .chevron{rotate:180deg}.panel{border:1px solid var(--l-color-border-overlay);border-radius:var(--border-radius);background-color:var(--background);box-shadow:var(--l-shadow-md);opacity:0;transition:opacity .12s ease, scale .12s ease, display .12s allow-discrete, overlay .12s allow-discrete;margin:0;padding:0;inset:auto;overflow:hidden;scale:.98}.panel:popover-open{opacity:1;scale:1}@starting-style{.panel:popover-open{opacity:0;scale:.98}}.listbox{overscroll-behavior:contain;max-block-size:16rem;margin:0;padding:.25rem;list-style:none;overflow-y:auto}.option{min-block-size:2rem;padding-block:.25rem;padding-inline:.5rem var(--height);border-radius:calc(var(--border-radius) - 2px);color:var(--l-color-text-primary);cursor:pointer;align-items:center;gap:.5rem;display:flex;position:relative}.option[aria-selected=true]{background-color:var(--l-color-bg-state-hover)}.option[aria-disabled=true]{opacity:.4;cursor:not-allowed}.option[data-current]:after{content:"";background-color:var(--l-form-control-activated-color);block-size:1em;inline-size:1em;-webkit-mask:var(--_check-icon) center / contain no-repeat;mask:var(--_check-icon) center / contain no-repeat;position:absolute;inset-inline-end:.5rem}.option-label{text-overflow:ellipsis;white-space:nowrap;flex:1;min-inline-size:0;overflow:hidden}.option-label mark{color:inherit;background:0 0;font-weight:600}.option-rich{flex:1;align-items:center;gap:.5rem;min-inline-size:0;display:flex}.option-rich .l-select-item-media{flex:none;align-items:center;font-size:1.25em;display:inline-flex}.option-rich .l-select-item-text{flex-direction:column;min-inline-size:0;display:flex}.option-rich .l-select-item-title{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.option-rich .l-select-item-description{color:var(--l-color-text-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:.85em;overflow:hidden}.empty{color:var(--l-color-text-tertiary);text-align:center;padding:.5rem}.visually-hidden{clip-path:inset(50%);white-space:nowrap;border:0;block-size:1px;inline-size:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}:host{--_chevron-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");--_x-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");--_check-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")}@media (prefers-reduced-motion:reduce){.panel,.chevron{transition-duration:0s}}`);function h(e){return e.normalize(`NFD`).replace(/[̀-ͯ]/g,``).toLowerCase()}var g=(e,t)=>{if(!t)return!0;let n=h(e.label);return h(t).split(/\s+/).filter(Boolean).every(e=>n.includes(e))},_=class extends Event{constructor(e){super(`change`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},v=class extends Event{constructor(e){super(`input`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},y=class extends d{constructor(...e){super(...e),this._localize=new c(this),this._listId=t(`combobox-list`),this._floating=new f(this,{getTriggerElement:()=>this._controlEl,getFloatingElement:()=>this._panelEl,getArrowElement:()=>null}),this._nav=new p(this,{listboxId:this._listId,getCount:()=>this._filtered.length,isDisabled:e=>this._filtered[e]?.disabled??!1,isOpen:()=>this._open,open:()=>this.show(),getOptionElements:()=>this.shadowRoot?.querySelectorAll(`.option`)}),this.#e=``,this.#t=``,this.#n=``,this.#r=`md`,this.#i=!1,this.#a=!1,this.#o=!0,this.#s=`bottom-start`,this.filter=g,this.#c=!1,this.#l=``,this.#u=[],this._onKeyDown=e=>{if(!this._nav.onKeyDown(e))switch(e.key){case`Enter`:this._open&&(e.preventDefault(),this._commitActiveOrCustom());break;case`Escape`:this._open?(e.preventDefault(),this.hide()):(this.value||this._inputEl?.value)&&this._clear();break;case`Tab`:this._open&&this._nav.activeIndex>=0&&this._commitActiveOrCustom();break;default:break}},this._onInput=e=>{this._query=e.target.value,this._nav.reset(),this._open||this.show(),this.dispatchEvent(new v(this._query))},this._onControlPointerDown=e=>{e.target.closest(`.clear`)||this._open||this.show()},this._onFocusOut=e=>{let t=e.relatedTarget;t&&this.shadowRoot?.contains(t)||(this.hasInteracted=!0,this._updateValidity(),this.hide())}}static{this.styles=[l,m]}#e;get value(){return this.#e}set value(e){this.#e=e}#t;get placeholder(){return this.#t}set placeholder(e){this.#t=e}#n;get label(){return this.#n}set label(e){this.#n=e}#r;get size(){return this.#r}set size(e){this.#r=e}#i;get withClear(){return this.#i}set withClear(e){this.#i=e}#a;get allowCustom(){return this.#a}set allowCustom(e){this.#a=e}#o;get highlight(){return this.#o}set highlight(e){this.#o=e}#s;get placement(){return this.#s}set placement(e){this.#s=e}#c;get _open(){return this.#c}set _open(e){this.#c=e}#l;get _query(){return this.#l}set _query(e){this.#l=e}#u;get _items(){return this.#u}set _items(e){this.#u=e}get _controlEl(){return this.shadowRoot?.querySelector(`.control`)??null}get _panelEl(){return this.shadowRoot?.querySelector(`.panel`)??null}get _inputEl(){return this.shadowRoot?.querySelector(`.input`)??null}connectedCallback(){super.connectedCallback(),this._readItems(),this._defaultFormValue=this.value,this._syncFormValue(this.value)}updated(e){e.has(`value`)&&(this._syncFormValue(this.value),this._updateValidity(),this._open||this._resetDisplay())}formResetCallback(){this.value=this._defaultFormValue,this._query=``,this._nav.reset(),super.formResetCallback(),this._resetDisplay()}formStateRestoreCallback(e){this.value=e,this._syncFormValue(e)}_readItems(){let t=this.querySelector(`datalist`),n=t?Array.from(t.options):[];this._items=n.map(t=>{let n=t.childElementCount>0,r=t.querySelector(`.${e(`select-item-title`)}`)?.textContent?.trim(),i=(t.getAttribute(`label`)||r||t.textContent||t.value).trim();return{value:t.value,label:i,disabled:t.disabled,html:n?t.innerHTML:void 0}})}_labelForValue(e){return this._items.find(t=>t.value===e)?.label??(this.allowCustom?e:``)}get _filtered(){return this._items.filter(e=>this.filter(e,this._query))}_resetDisplay(){let e=this._inputEl;e&&(e.value=this._labelForValue(this.value))}_updateValidity(){this.required&&!this.value?this.setValidity({valueMissing:!0},this._localize.term(`selectOption`),this._inputEl??void 0):this.setValidity({})}show(){this._open||this.disabled||(this._readItems(),this.dispatchEvent(new Event(`show`,{cancelable:!0}))&&(this._open=!0,this.value&&!this._query&&this._nav.setActive(this._filtered.findIndex(e=>e.value===this.value)),this.updateComplete.then(()=>{this._panelEl?.showPopover?.(),this._floating.startPositioning({placement:this.placement,distance:4,minWidth:`trigger`})})))}hide(){if(!this._open||!this.dispatchEvent(new Event(`hide`,{cancelable:!0})))return;this._open=!1,this._nav.reset();let e=this._panelEl;e?.matches?.(`:popover-open`)&&e.hidePopover?.(),this._floating.stopPositioning(),this._resetDisplay()}_commit(e){if(e.disabled)return;this.value=e.value,this._query=``,this.hasInteracted=!0;let t=this._inputEl;t&&(t.value=e.label),this._syncFormValue(this.value),this._updateValidity(),this.dispatchEvent(new _(this.value)),this.hide(),t?.focus()}_commitActiveOrCustom(){let e=this._filtered,t=this._nav.activeIndex;if(t>=0&&e[t]){this._commit(e[t]);return}let n=this._inputEl;this.allowCustom&&n&&(this.value=n.value,this._syncFormValue(this.value),this._updateValidity(),this.dispatchEvent(new _(this.value)),this.hide())}_clear(){this.value=``,this._query=``,this._nav.reset(),this._inputEl&&(this._inputEl.value=``),this._syncFormValue(``),this._updateValidity(),this.dispatchEvent(new _(``)),this._inputEl?.focus()}_highlight(e){let t=this._query.trim();if(!this.highlight||!t)return e;let n=h(e).indexOf(h(t).split(/\s+/)[0]);return n<0?e:o`${e.slice(0,n)}<mark>${e.slice(n,n+t.length)}</mark>${e.slice(n+t.length)}`}render(){let e=this._filtered,t=this._nav.activeDescendant,n=this._nav.activeIndex,r=this.required&&!this.value&&this.hasInteracted,i=this._open?e.length===0?this._localize.term(`noResults`):`${e.length} ${this._localize.term(`suggestions`)}`:``;return o`
|
|
1
|
+
import{cls as e,uniqueId as t}from"../../registry.js";import{i as n}from"../../chunks/lit.js";import{i as r,r as i,t as a}from"../../chunks/decorate.js";import{a as o,t as s}from"../../chunks/lit-html.js";import{LocalizeController as c}from"../../shared/localize.js";import l from"../../shared/styles/host.styles.js";import{t as u}from"../../chunks/unsafe-html.js";import{LuxenFormAssociatedElement as d}from"../../shared/luxen-form-associated-element.js";import{PopoverController as f}from"../../shared/controllers/popover.js";import{ListboxNavController as p}from"../../shared/controllers/listbox-nav.js";var m=n(`:host{--height:var(--l-form-control-height);--border-radius:var(--l-form-control-border-radius);--background:var(--l-color-surface-overlay);inline-size:100%;display:block}:host([size=xs]){--height:var(--l-size-control-xs)}:host([size=sm]){--height:var(--l-size-control-sm)}:host([size=lg]){--height:var(--l-size-control-lg)}:host([size=xl]){--height:var(--l-size-control-xl)}:host([disabled]){opacity:.5;pointer-events:none}.base{position:relative}.control{block-size:var(--height);padding-inline:var(--l-form-control-padding-inline);border:var(--l-form-control-border-width) solid var(--l-form-control-border-color);border-radius:var(--border-radius);background-color:var(--l-form-control-background-color);cursor:text;align-items:center;gap:.25rem;display:flex}@media (hover:hover){.control:hover{border-color:var(--l-form-control-border-color-hover)}}.control:has(.input:focus-visible){border-color:var(--l-focus-ring);box-shadow:0 0 0 3px color-mix(in oklab, var(--l-focus-ring) 22%, transparent)}.input{min-inline-size:0;color:var(--l-form-control-value-color);font:inherit;background:0 0;border:0;outline:none;flex:1}.input::placeholder{color:var(--l-form-control-placeholder-color)}.chevron{block-size:1em;inline-size:1em;color:var(--l-form-control-placeholder-color);-webkit-mask:var(--_chevron-icon) center / contain no-repeat;mask:var(--_chevron-icon) center / contain no-repeat;background-color:currentColor;flex:none;transition:rotate .15s}.clear{cursor:pointer;block-size:1.5rem;inline-size:1.5rem;color:var(--l-form-control-placeholder-color);-webkit-mask:var(--_x-icon) center / 1em no-repeat;mask:var(--_x-icon) center / 1em no-repeat;background-color:currentColor;border:0;flex:none;padding:0}@media (hover:hover){.clear:hover{color:var(--l-form-control-value-color)}}.control:has(.input[aria-expanded=true]) .chevron{rotate:180deg}.panel{border:1px solid var(--l-color-border-overlay);border-radius:var(--border-radius);background-color:var(--background);box-shadow:var(--l-shadow-md);opacity:0;transition:opacity .12s ease, scale .12s ease, display .12s allow-discrete, overlay .12s allow-discrete;margin:0;padding:0;inset:auto;overflow:hidden;scale:.98}.panel:popover-open{opacity:1;scale:1}@starting-style{.panel:popover-open{opacity:0;scale:.98}}.listbox{overscroll-behavior:contain;max-block-size:16rem;margin:0;padding:.25rem;list-style:none;overflow-y:auto}.option{min-block-size:2rem;padding-block:.25rem;padding-inline:.5rem var(--height);border-radius:calc(var(--border-radius) - 2px);color:var(--l-color-text-primary);cursor:pointer;align-items:center;gap:.5rem;display:flex;position:relative}.option[aria-selected=true]{background-color:var(--l-color-bg-state-hover)}.option[aria-disabled=true]{opacity:.4;cursor:not-allowed}.option[data-current]:after{content:"";background-color:var(--l-form-control-activated-color);block-size:1em;inline-size:1em;-webkit-mask:var(--_check-icon) center / contain no-repeat;mask:var(--_check-icon) center / contain no-repeat;position:absolute;inset-inline-end:.5rem}.option-label{text-overflow:ellipsis;white-space:nowrap;flex:1;min-inline-size:0;overflow:hidden}.option-label mark{color:inherit;font-weight:var(--l-font-weight-semibold);background:0 0}.option-rich{flex:1;align-items:center;gap:.5rem;min-inline-size:0;display:flex}.option-rich .l-select-item-media{flex:none;align-items:center;font-size:1.25em;display:inline-flex}.option-rich .l-select-item-text{flex-direction:column;min-inline-size:0;display:flex}.option-rich .l-select-item-title{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.option-rich .l-select-item-description{color:var(--l-color-text-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:.85em;overflow:hidden}.empty{color:var(--l-color-text-tertiary);text-align:center;padding:.5rem}.visually-hidden{clip-path:inset(50%);white-space:nowrap;border:0;block-size:1px;inline-size:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}:host{--_chevron-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");--_x-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");--_check-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")}@media (prefers-reduced-motion:reduce){.panel,.chevron{transition-duration:0s}}`);function h(e){return e.normalize(`NFD`).replace(/[̀-ͯ]/g,``).toLowerCase()}var g=(e,t)=>{if(!t)return!0;let n=h(e.label);return h(t).split(/\s+/).filter(Boolean).every(e=>n.includes(e))},_=class extends Event{constructor(e){super(`change`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},v=class extends Event{constructor(e){super(`input`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},y=class extends d{constructor(...e){super(...e),this._localize=new c(this),this._listId=t(`combobox-list`),this._floating=new f(this,{getTriggerElement:()=>this._controlEl,getFloatingElement:()=>this._panelEl,getArrowElement:()=>null}),this._nav=new p(this,{listboxId:this._listId,getCount:()=>this._filtered.length,isDisabled:e=>this._filtered[e]?.disabled??!1,isOpen:()=>this._open,open:()=>this.show(),getOptionElements:()=>this.shadowRoot?.querySelectorAll(`.option`)}),this.#e=``,this.#t=``,this.#n=``,this.#r=`md`,this.#i=!1,this.#a=!1,this.#o=!0,this.#s=`bottom-start`,this.filter=g,this.#c=!1,this.#l=``,this.#u=[],this._onKeyDown=e=>{if(!this._nav.onKeyDown(e))switch(e.key){case`Enter`:this._open&&(e.preventDefault(),this._commitActiveOrCustom());break;case`Escape`:this._open?(e.preventDefault(),this.hide()):(this.value||this._inputEl?.value)&&this._clear();break;case`Tab`:this._open&&this._nav.activeIndex>=0&&this._commitActiveOrCustom();break;default:break}},this._onInput=e=>{this._query=e.target.value,this._nav.reset(),this._open||this.show(),this.dispatchEvent(new v(this._query))},this._onControlPointerDown=e=>{e.target.closest(`.clear`)||this._open||this.show()},this._onFocusOut=e=>{let t=e.relatedTarget;t&&this.shadowRoot?.contains(t)||(this.hasInteracted=!0,this._updateValidity(),this.hide())}}static{this.styles=[l,m]}#e;get value(){return this.#e}set value(e){this.#e=e}#t;get placeholder(){return this.#t}set placeholder(e){this.#t=e}#n;get label(){return this.#n}set label(e){this.#n=e}#r;get size(){return this.#r}set size(e){this.#r=e}#i;get withClear(){return this.#i}set withClear(e){this.#i=e}#a;get allowCustom(){return this.#a}set allowCustom(e){this.#a=e}#o;get highlight(){return this.#o}set highlight(e){this.#o=e}#s;get placement(){return this.#s}set placement(e){this.#s=e}#c;get _open(){return this.#c}set _open(e){this.#c=e}#l;get _query(){return this.#l}set _query(e){this.#l=e}#u;get _items(){return this.#u}set _items(e){this.#u=e}get _controlEl(){return this.shadowRoot?.querySelector(`.control`)??null}get _panelEl(){return this.shadowRoot?.querySelector(`.panel`)??null}get _inputEl(){return this.shadowRoot?.querySelector(`.input`)??null}connectedCallback(){super.connectedCallback(),this._readItems(),this._defaultFormValue=this.value,this._syncFormValue(this.value)}updated(e){e.has(`value`)&&(this._syncFormValue(this.value),this._updateValidity(),this._open||this._resetDisplay())}formResetCallback(){this.value=this._defaultFormValue,this._query=``,this._nav.reset(),super.formResetCallback(),this._resetDisplay()}formStateRestoreCallback(e){this.value=e,this._syncFormValue(e)}_readItems(){let t=this.querySelector(`datalist`),n=t?Array.from(t.options):[];this._items=n.map(t=>{let n=t.childElementCount>0,r=t.querySelector(`.${e(`select-item-title`)}`)?.textContent?.trim(),i=(t.getAttribute(`label`)||r||t.textContent||t.value).trim();return{value:t.value,label:i,disabled:t.disabled,html:n?t.innerHTML:void 0}})}_labelForValue(e){return this._items.find(t=>t.value===e)?.label??(this.allowCustom?e:``)}get _filtered(){return this._items.filter(e=>this.filter(e,this._query))}_resetDisplay(){let e=this._inputEl;e&&(e.value=this._labelForValue(this.value))}_updateValidity(){this.required&&!this.value?this.setValidity({valueMissing:!0},this._localize.term(`selectOption`),this._inputEl??void 0):this.setValidity({})}show(){this._open||this.disabled||(this._readItems(),this.dispatchEvent(new Event(`show`,{cancelable:!0}))&&(this._open=!0,this.value&&!this._query&&this._nav.setActive(this._filtered.findIndex(e=>e.value===this.value)),this.updateComplete.then(()=>{this._panelEl?.showPopover?.(),this._floating.startPositioning({placement:this.placement,distance:4,minWidth:`trigger`})})))}hide(){if(!this._open||!this.dispatchEvent(new Event(`hide`,{cancelable:!0})))return;this._open=!1,this._nav.reset();let e=this._panelEl;e?.matches?.(`:popover-open`)&&e.hidePopover?.(),this._floating.stopPositioning(),this._resetDisplay()}_commit(e){if(e.disabled)return;this.value=e.value,this._query=``,this.hasInteracted=!0;let t=this._inputEl;t&&(t.value=e.label),this._syncFormValue(this.value),this._updateValidity(),this.dispatchEvent(new _(this.value)),this.hide(),t?.focus()}_commitActiveOrCustom(){let e=this._filtered,t=this._nav.activeIndex;if(t>=0&&e[t]){this._commit(e[t]);return}let n=this._inputEl;this.allowCustom&&n&&(this.value=n.value,this._syncFormValue(this.value),this._updateValidity(),this.dispatchEvent(new _(this.value)),this.hide())}_clear(){this.value=``,this._query=``,this._nav.reset(),this._inputEl&&(this._inputEl.value=``),this._syncFormValue(``),this._updateValidity(),this.dispatchEvent(new _(``)),this._inputEl?.focus()}_highlight(e){let t=this._query.trim();if(!this.highlight||!t)return e;let n=h(e).indexOf(h(t).split(/\s+/)[0]);return n<0?e:o`${e.slice(0,n)}<mark>${e.slice(n,n+t.length)}</mark>${e.slice(n+t.length)}`}render(){let e=this._filtered,t=this._nav.activeDescendant,n=this._nav.activeIndex,r=this.required&&!this.value&&this.hasInteracted,i=this._open?e.length===0?this._localize.term(`noResults`):`${e.length} ${this._localize.term(`suggestions`)}`:``;return o`
|
|
2
2
|
<div
|
|
3
3
|
class="base"
|
|
4
4
|
part="base"
|