use-wc 1.0.0-pre.33 → 1.0.0-pre.35

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.
@@ -396,6 +396,71 @@
396
396
  }
397
397
  ]
398
398
  },
399
+ {
400
+ "kind": "javascript-module",
401
+ "path": "src/elements/use-calendarday/use-calendarday.ts",
402
+ "declarations": [
403
+ {
404
+ "kind": "class",
405
+ "description": "A helper component for customizing specific days within `use-calendar`.\nContent placed inside this element will replace the default day number display.",
406
+ "name": "UseCalendarday",
407
+ "slots": [
408
+ {
409
+ "description": "slot for custom day content (replaces the day number)",
410
+ "name": "default"
411
+ }
412
+ ],
413
+ "members": [
414
+ {
415
+ "kind": "field",
416
+ "name": "date",
417
+ "type": {
418
+ "text": "string"
419
+ },
420
+ "attribute": "date"
421
+ },
422
+ {
423
+ "kind": "field",
424
+ "name": "day",
425
+ "readonly": true
426
+ }
427
+ ],
428
+ "attributes": [
429
+ {
430
+ "name": "date",
431
+ "type": {
432
+ "text": "string"
433
+ },
434
+ "fieldName": "date"
435
+ }
436
+ ],
437
+ "superclass": {
438
+ "name": "LitElement",
439
+ "package": "lit"
440
+ },
441
+ "tagName": "use-calendarday",
442
+ "customElement": true
443
+ }
444
+ ],
445
+ "exports": [
446
+ {
447
+ "kind": "js",
448
+ "name": "UseCalendarday",
449
+ "declaration": {
450
+ "name": "UseCalendarday",
451
+ "module": "src/elements/use-calendarday/use-calendarday.ts"
452
+ }
453
+ },
454
+ {
455
+ "kind": "custom-element-definition",
456
+ "name": "use-calendarday",
457
+ "declaration": {
458
+ "name": "UseCalendarday",
459
+ "module": "src/elements/use-calendarday/use-calendarday.ts"
460
+ }
461
+ }
462
+ ]
463
+ },
399
464
  {
400
465
  "kind": "javascript-module",
401
466
  "path": "src/elements/use-date-input/use-date-input.ts",
@@ -522,71 +587,6 @@
522
587
  }
523
588
  ]
524
589
  },
525
- {
526
- "kind": "javascript-module",
527
- "path": "src/elements/use-calendarday/use-calendarday.ts",
528
- "declarations": [
529
- {
530
- "kind": "class",
531
- "description": "A helper component for customizing specific days within `use-calendar`.\nContent placed inside this element will replace the default day number display.",
532
- "name": "UseCalendarday",
533
- "slots": [
534
- {
535
- "description": "slot for custom day content (replaces the day number)",
536
- "name": "default"
537
- }
538
- ],
539
- "members": [
540
- {
541
- "kind": "field",
542
- "name": "date",
543
- "type": {
544
- "text": "string"
545
- },
546
- "attribute": "date"
547
- },
548
- {
549
- "kind": "field",
550
- "name": "day",
551
- "readonly": true
552
- }
553
- ],
554
- "attributes": [
555
- {
556
- "name": "date",
557
- "type": {
558
- "text": "string"
559
- },
560
- "fieldName": "date"
561
- }
562
- ],
563
- "superclass": {
564
- "name": "LitElement",
565
- "package": "lit"
566
- },
567
- "tagName": "use-calendarday",
568
- "customElement": true
569
- }
570
- ],
571
- "exports": [
572
- {
573
- "kind": "js",
574
- "name": "UseCalendarday",
575
- "declaration": {
576
- "name": "UseCalendarday",
577
- "module": "src/elements/use-calendarday/use-calendarday.ts"
578
- }
579
- },
580
- {
581
- "kind": "custom-element-definition",
582
- "name": "use-calendarday",
583
- "declaration": {
584
- "name": "UseCalendarday",
585
- "module": "src/elements/use-calendarday/use-calendarday.ts"
586
- }
587
- }
588
- ]
589
- },
590
590
  {
591
591
  "kind": "javascript-module",
592
592
  "path": "src/elements/use-date-picker/use-date-picker.ts",
@@ -2413,6 +2413,105 @@
2413
2413
  }
2414
2414
  ]
2415
2415
  },
2416
+ {
2417
+ "kind": "javascript-module",
2418
+ "path": "src/elements/use-intl-datetime/use-intl-datetime.ts",
2419
+ "declarations": [
2420
+ {
2421
+ "kind": "class",
2422
+ "description": "Displays a localized, human-readable representation of a date, time, or datetime.\nRenders a semantic `<time>` element in its shadow root with a machine-readable\n`datetime` attribute and formatted inner text.\n\nSet `datestyle`, `timestyle`, or both to control what is formatted and how.\nThe presence of each attribute determines the format mode:\n- `datestyle` only → date formatting\n- `timestyle` only → time formatting\n- both → date and time formatting\n\nLocale is resolved from the nearest ancestor `[lang]` attribute, or\n`navigator.language` if none is found. Set `lang` directly on the element to override.",
2423
+ "name": "UseIntlDatetime",
2424
+ "members": [
2425
+ {
2426
+ "kind": "field",
2427
+ "name": "value",
2428
+ "type": {
2429
+ "text": "string | undefined"
2430
+ },
2431
+ "attribute": "value"
2432
+ },
2433
+ {
2434
+ "kind": "field",
2435
+ "name": "datestyle",
2436
+ "type": {
2437
+ "text": "string | undefined"
2438
+ },
2439
+ "attribute": "datestyle"
2440
+ },
2441
+ {
2442
+ "kind": "field",
2443
+ "name": "timestyle",
2444
+ "type": {
2445
+ "text": "string | undefined"
2446
+ },
2447
+ "attribute": "timestyle"
2448
+ }
2449
+ ],
2450
+ "attributes": [
2451
+ {
2452
+ "type": {
2453
+ "text": "string | undefined"
2454
+ },
2455
+ "description": "ISO date/time string or Unix timestamp (ms)",
2456
+ "name": "value",
2457
+ "fieldName": "value"
2458
+ },
2459
+ {
2460
+ "type": {
2461
+ "text": "string | undefined"
2462
+ },
2463
+ "description": "Date format style: `short` | `medium` | `long` | `full`",
2464
+ "name": "datestyle",
2465
+ "fieldName": "datestyle"
2466
+ },
2467
+ {
2468
+ "type": {
2469
+ "text": "string | undefined"
2470
+ },
2471
+ "description": "Time format style: `short` | `medium` | `long` | `full`",
2472
+ "name": "timestyle",
2473
+ "fieldName": "timestyle"
2474
+ },
2475
+ {
2476
+ "name": "lang",
2477
+ "type": {
2478
+ "text": "string"
2479
+ },
2480
+ "fieldName": "lang",
2481
+ "description": "BCP 47 locale tag. Inherits from nearest ancestor `[lang]` if not set.",
2482
+ "inheritedFrom": {
2483
+ "name": "UseLocaleElement",
2484
+ "module": "src/elements/use-locale-element/use-locale-element.ts"
2485
+ }
2486
+ }
2487
+ ],
2488
+ "superclass": {
2489
+ "name": "UseLocaleElement",
2490
+ "module": "/src/elements/use-locale-element/use-locale-element"
2491
+ },
2492
+ "tagName": "use-intl-datetime",
2493
+ "customElement": true
2494
+ }
2495
+ ],
2496
+ "exports": [
2497
+ {
2498
+ "kind": "js",
2499
+ "name": "UseIntlDatetime",
2500
+ "declaration": {
2501
+ "name": "UseIntlDatetime",
2502
+ "module": "src/elements/use-intl-datetime/use-intl-datetime.ts"
2503
+ }
2504
+ },
2505
+ {
2506
+ "kind": "custom-element-definition",
2507
+ "name": "use-intl-datetime",
2508
+ "declaration": {
2509
+ "name": "UseIntlDatetime",
2510
+ "module": "src/elements/use-intl-datetime/use-intl-datetime.ts"
2511
+ }
2512
+ }
2513
+ ]
2514
+ },
2416
2515
  {
2417
2516
  "kind": "javascript-module",
2418
2517
  "path": "src/elements/use-listbox-input/use-listbox-input.ts",
@@ -134,7 +134,7 @@
134
134
  --usewc-layout-focus-ring-offset-outside: var(--usewc-space-2);
135
135
  --usewc-layout-focus-ring-offset-inside: var(--usewc-space-none);
136
136
  --usewc-effect-focus-ring-style: solid;
137
- --usewc-transition-focus-ring: 0.05s ease-in-out;
137
+ --usewc-transition-focus-ring: outline 0.05s ease-in-out;
138
138
  --usewc-effect-control-opacity-disabled: 0.5;
139
139
  /* - Link */
140
140
  --usewc-color-link-text-static: var(--usewc-color-blue-500);
@@ -175,8 +175,12 @@
175
175
  --usewc-color-input-segment-background-focus: var(--usewc-color-blue-100);
176
176
  --usewc-color-input-segment-text-focus: var(--usewc-color-gray-700);
177
177
  --usewc-effect-dropdown-trigger-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 16L5.0718 8.5L18.9282 8.5L12 16Z' fill='rgba(255,255,255,0.5' /%3E%3C/svg%3E");
178
+ --usewc-effect-dropdown-trigger-side-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M16 12L8.5 18.9282L8.5 5.0718Z' fill='rgba(255,255,255,0.5' /%3E%3C/svg%3E");
178
179
  --usewc-effect-dropdown-trigger-background-size: 1em;
179
180
  --usewc-effect-dropdown-trigger-background-blend-mode: difference;
181
+ --usewc-effect-menu-item-checkmark-background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 13L10 18L19 7' stroke='rgba(255,255,255,0.5)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C%2Fsvg%3E");
182
+ --usewc-effect-menu-item-checkmark-background-size: 1em;
183
+ --usewc-effect-menu-item-checkmark-background-blend-mode: difference;
180
184
  /* - Layout */
181
185
  --usewc-layout-input-border: var(--usewc-space-1-relative);
182
186
  --usewc-layout-input-padding-block: calc(var(--usewc-space-4) - var(--usewc-layout-input-border));
@@ -312,6 +316,30 @@
312
316
  --usewc-layout-button-extra-large-font-size: var(--usewc-font-size-24);
313
317
  --usewc-layout-button-extra-large-line-height: var(--usewc-line-height-28);
314
318
 
319
+ /* Menu */
320
+ --usewc-layout-popover-menu-item-padding-inline: var(--usewc-space-4);
321
+ --usewc-layout-popover-menu-item-padding-block: var(--usewc-space-2);
322
+ --usewc-layout-popover-menu-item-line-height: var(--usewc-line-height-24);
323
+ --usewc-color-popover-menu-item-background-static: var(--usewc-color-transparent);
324
+ --usewc-color-popover-menu-item-background-hover: var(--usewc-color-gray-800);
325
+ --usewc-color-popover-menu-item-background-active: var(--usewc-color-gray-800);
326
+ --usewc-effect-popover-menu-item-border-radius: var(--usewc-effect-border-radius-4);
327
+ --usewc-layout-popover-menu-anchor-offset: var(--usewc-space-4);
328
+ --usewc-layout-popover-menu-padding: var(--usewc-space-4);
329
+ --usewc-layout-popover-menu-border: var(--usewc-space-1-relative);
330
+ --usewc-effect-popover-menu-border-style: var(--usewc-effect-border-solid);
331
+ --usewc-color-popover-menu-background: var(--usewc-color-canvas-background);
332
+ --usewc-color-popover-menu-border: var(--usewc-color-gray-600);
333
+ --usewc-effect-popover-menu-border-radius: var(--usewc-effect-border-radius-8);
334
+ --usewc-layout-popover-menu-header-font-size: var(--usewc-font-size-14);
335
+ --usewc-font-popover-menu-header-weight: var(--usewc-font-weight-medium);
336
+ --usewc-color-popover-menu-header-text: var(--usewc-color-gray-400);
337
+ --usewc-font-popover-menu-shortcut: var(--usewc-font-family-monospace);
338
+ --usewc-color-popover-menu-shortcut: var(--usewc-color-gray-400);
339
+ --usewc-color-popover-menu-item-text-static: var(--usewc-color-button-base-text-static);
340
+ --usewc-color-popover-menu-item-text-hover: var(--usewc-color-button-base-text-static);
341
+ --usewc-color-popover-menu-item-text-focus: var(--usewc-color-button-base-text-static);
342
+
315
343
  /* Inline code */
316
344
  --usewc-layout-code-padding-inline: var(--usewc-space-4);
317
345
  --usewc-layout-code-padding-block: var(--usewc-space-none);
@@ -328,7 +356,7 @@
328
356
  --usewc-color-document-text: var(--usewc-color-gray-200);
329
357
  --usewc-color-document-text-muted: var(--usewc-color-gray-300);
330
358
  --usewc-color-document-background: var(--usewc-color-gray-800);
331
- --usewc-color-canvas-background: var(--usewc-color-white);
359
+ --usewc-color-canvas-background: var(--usewc-color-black);
332
360
  --usewc-color-focus-ring: var(--usewc-color-blue-200);
333
361
  --usewc-color-input-background-static: oklch(from var(--usewc-color-gray-100) l c h / 0.025);
334
362
  --usewc-color-input-border-static: var(--usewc-color-gray-600);
@@ -14,9 +14,10 @@
14
14
  font-size: var(--usewc-layout-document-text-size);
15
15
  }
16
16
 
17
- :is(button, a, details summary):not([data-appear-as="native"]):focus-visible,
17
+ :is(button, a, details summary, use-widget):not([data-appear-as="native"]):focus-visible,
18
18
  :is(input, textarea, select, use-date, use-time, use-datetime, use-duration):not([data-appear-as="native"]):focus,
19
19
  input[type="file"]:not([data-appear-as="native"]):focus-visible,
20
+ use-dropdown:not([data-appear-as="native"])::part(trigger):focus-visible,
20
21
  [data-appear-as="input"]:has(input:focus) {
21
22
  outline: var(--usewc-layout-focus-ring-size) var(--usewc-effect-focus-ring-style) var(--usewc-color-focus-ring);
22
23
  outline-offset: var(--usewc-layout-focus-ring-offset-outside);
@@ -32,7 +33,8 @@
32
33
  use-time:not([data-appear-as="native"]),
33
34
  use-datetime:not([data-appear-as="native"]),
34
35
  use-duration:not([data-appear-as="native"])
35
- ) {
36
+ ),
37
+ use-listbox-input:not([data-appear-as="native"])::part(listbox) {
36
38
  border: var(--usewc-layout-input-border) var(--usewc-effect-input-border-style)
37
39
  var(--usewc-color-input-border-static);
38
40
  line-height: var(--usewc-layout-input-line-height);
@@ -71,15 +73,12 @@
71
73
  }
72
74
  }
73
75
 
76
+ use-listbox-input:not([data-appear-as="native"])::part(listbox) {
77
+ padding: var(--usewc-layout-popover-menu-padding);
78
+ }
79
+
74
80
  select:not([data-appear-as="native"]) {
75
81
  appearance: none;
76
- padding-inline-end: calc(var(--usewc-layout-input-padding-inline) * 2 + var(--usewc-layout-selector-width));
77
- background-image: var(--usewc-effect-dropdown-trigger-background-image, none);
78
- /* TODO use logical position */
79
- background-position: right var(--usewc-layout-input-padding-inline) center;
80
- background-repeat: no-repeat;
81
- background-size: var(--usewc-effect-dropdown-trigger-background-size, 1em);
82
- background-blend-mode: var(--usewc-effect-dropdown-trigger-background-blend-mode, none);
83
82
  }
84
83
 
85
84
  [data-appear-as="input"] {
@@ -212,6 +211,7 @@
212
211
  }
213
212
 
214
213
  :is(button:not([data-appear-as]), [data-appear-as="button"]),
214
+ use-dropdown,
215
215
  input[type="file"]:not([data-appear-as]) {
216
216
  &:where(:not(button)),
217
217
  &::file-selector-button {
@@ -233,7 +233,8 @@
233
233
  --usewc-theme-color-button-background-active: var(--usewc-color-button-base-background-active);
234
234
  --usewc-theme-color-button-border-active: var(--usewc-color-button-base-border-active);
235
235
 
236
- &:not([type="file"]),
236
+ &::part(trigger),
237
+ &:not([type="file"], use-dropdown),
237
238
  &::file-selector-button {
238
239
  display: inline-flex;
239
240
  align-items: center;
@@ -254,18 +255,24 @@
254
255
  var(--usewc-theme-color-button-border-static);
255
256
  }
256
257
 
258
+ &:is(use-dropdown) {
259
+ display: contents;
260
+ }
261
+
257
262
  &::file-selector-button {
258
263
  margin-inline-end: var(--usewc-layout-input-gap-inline);
259
264
  }
260
265
 
261
- &:is(:hover, :focus-visible):not([type="file"]),
266
+ &:is(:hover, :focus-visible):not([type="file"], use-dropdown),
267
+ &::part(trigger):is(:hover, :focus-visible),
262
268
  &:is(:hover, :focus-visible)::file-selector-button {
263
269
  background: var(--usewc-theme-color-button-background-hover);
264
270
  border-color: var(--usewc-theme-color-button-border-hover);
265
271
  color: var(--usewc-theme-color-button-text-hover);
266
272
  }
267
273
 
268
- &:active:not([type="file"]),
274
+ &:active:not([type="file"], use-dropdown),
275
+ &:active::part(trigger),
269
276
  &:active::file-selector-button {
270
277
  background: var(--usewc-theme-color-button-background-active);
271
278
  border-color: var(--usewc-theme-color-button-border-active);
@@ -523,4 +530,152 @@
523
530
  gap: var(--usewc-layout-input-segment-padding-inline);
524
531
  }
525
532
  }
533
+
534
+ select:not([data-appear-as="native"]),
535
+ use-dropdown::part(trigger),
536
+ use-dropdown use-dropdown::part(trigger) {
537
+ padding-inline-end: calc(var(--usewc-layout-input-padding-inline) * 2 + var(--usewc-layout-selector-width));
538
+ background-image: var(--usewc-effect-dropdown-trigger-background-image, none);
539
+ /* TODO use logical position */
540
+ background-position: right var(--usewc-layout-input-padding-inline) center;
541
+ background-repeat: no-repeat;
542
+ background-size: var(--usewc-effect-dropdown-trigger-background-size, 1em);
543
+ background-blend-mode: var(--usewc-effect-dropdown-trigger-background-blend-mode, none);
544
+ }
545
+
546
+ use-dropdown use-dropdown::part(trigger) {
547
+ background-image: var(--usewc-effect-dropdown-trigger-side-background-image);
548
+ background-position: right center;
549
+ }
550
+
551
+ select:not([data-appear-as="native"]),
552
+ use-dropdown::part(trigger),
553
+ use-dropdown use-dropdown::part(trigger) {
554
+ anchor-name: --use-popover-trigger;
555
+ }
556
+
557
+ use-dropdown::part(trigger-icon-default),
558
+ use-option::part(selected-indicator-default) {
559
+ display: none;
560
+ }
561
+
562
+ use-dropdown::part(menu) {
563
+ border: var(--usewc-layout-popover-menu-border) var(--usewc-effect-popover-menu-border-style)
564
+ var(--usewc-color-popover-menu-border);
565
+ padding: var(--usewc-layout-popover-menu-padding);
566
+ background: var(--usewc-color-popover-menu-background);
567
+ border-radius: var(--usewc-effect-popover-menu-border-radius);
568
+ margin: unset;
569
+ }
570
+
571
+ use-dropdown::part(menu) {
572
+ inset: unset;
573
+ position: fixed;
574
+ position-anchor: --use-popover-trigger;
575
+ inset-block-start: calc(anchor(end) + var(--usewc-layout-popover-menu-anchor-offset));
576
+ inset-inline-start: anchor(start);
577
+ position-try-fallbacks:
578
+ flip-block,
579
+ flip-inline,
580
+ flip-inline flip-block;
581
+ }
582
+
583
+ use-option,
584
+ use-dropdown :is([role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]),
585
+ use-dropdown use-dropdown::part(trigger) {
586
+ border: none;
587
+ text-align: start;
588
+ cursor: default;
589
+ display: flex;
590
+ flex-direction: row;
591
+ justify-content: start;
592
+ gap: var(--usewc-layout-popover-menu-item-padding-inline);
593
+ line-height: var(--usewc-layout-popover-menu-item-line-height);
594
+ padding-inline: var(--usewc-layout-popover-menu-item-padding-inline);
595
+ padding-block: var(--usewc-layout-popover-menu-item-padding-block);
596
+ background-color: var(--usewc-color-popover-menu-item-background-static);
597
+ border-radius: var(--usewc-effect-popover-menu-item-border-radius);
598
+ color: var(--usewc-color-popover-menu-item-text-static);
599
+ text-decoration: none;
600
+
601
+ > *:last-child:not(:first-child) {
602
+ flex: 0 0 auto;
603
+ margin-inline-start: auto;
604
+ }
605
+ }
606
+
607
+ use-listbox-input:is(:hover, :focus) use-option:state(active) {
608
+ background-color: var(--usewc-color-popover-menu-item-background-active);
609
+ }
610
+
611
+ use-dropdown :is([role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], use-dropdown),
612
+ use-listbox-input {
613
+ &:not(use-dropdown):hover,
614
+ &::part(trigger):hover {
615
+ background-color: var(--usewc-color-popover-menu-item-background-hover);
616
+ color: var(--usewc-color-popover-menu-item-text-hover);
617
+ }
618
+
619
+ &:focus-visible,
620
+ &::part(trigger):focus-visible {
621
+ background-color: var(--usewc-color-popover-menu-item-background-static);
622
+ outline: var(--usewc-layout-focus-ring-size) var(--usewc-effect-focus-ring-style) var(--usewc-color-focus-ring);
623
+ outline-offset: var(--usewc-layout-focus-ring-offset-inside);
624
+ transition: var(--usewc-transition-focus-ring);
625
+ color: var(--usewc-color-popover-menu-item-text-focus);
626
+ }
627
+ }
628
+
629
+ use-listbox-input,
630
+ use-dropdown :is([role="menuitemcheckbox"], [role="menuitemradio"]) {
631
+ use-option,
632
+ &:has(+ :is([role="menuitemcheckbox"], [role="menuitemradio"])),
633
+ & + :is(:is([role="menuitemcheckbox"], [role="menuitemradio"])) {
634
+ padding-inline-start: calc(var(--usewc-layout-input-padding-inline) * 2 + var(--usewc-layout-selector-width));
635
+ }
636
+ }
637
+
638
+ use-dropdown,
639
+ use-listbox-input {
640
+ [role="group"][aria-label] {
641
+ &::before {
642
+ content: attr(aria-label);
643
+ padding: var(--usewc-layout-popover-menu-padding);
644
+ font-size: var(--usewc-layout-popover-menu-header-font-size);
645
+ font-weight: var(--usewc-effect-popover-menu-header-font-weight);
646
+ color: var(--usewc-color-popover-menu-header-text);
647
+ }
648
+ }
649
+
650
+ kbd {
651
+ font-family: var(--usewc-font-popover-menu-shortcut);
652
+ color: var(--usewc-color-popover-menu-shortcut);
653
+ margin-inline-start: auto;
654
+ }
655
+
656
+ hr {
657
+ border: 0;
658
+ border-block-start: var(--usewc-layout-popover-menu-border) var(--usewc-effect-popover-menu-border-style)
659
+ var(--usewc-color-popover-menu-border);
660
+ margin-block: var(--usewc-layout-popover-menu-padding);
661
+ }
662
+ }
663
+
664
+ use-dropdown use-dropdown::part(menu) {
665
+ margin-inline-start: 0.5rem;
666
+ inset-block-start: calc(
667
+ anchor(start) - var(--usewc-layout-popover-menu-padding) - var(--usewc-layout-popover-menu-border)
668
+ );
669
+ inset-inline-start: anchor(end);
670
+ }
671
+
672
+ use-dropdown [aria-checked="true"],
673
+ use-option:state(selected) {
674
+ background-image: var(--usewc-effect-menu-item-checkmark-background-image, none);
675
+ /* TODO use logical position */
676
+ background-position: left var(--usewc-layout-input-padding-inline) center;
677
+ background-repeat: no-repeat;
678
+ background-size: var(--usewc-effect-menu-item-checkmark-background-size, 1em);
679
+ background-blend-mode: var(--usewc-effect-menu-item-checkmark-background-blend-mode, none);
680
+ }
526
681
  }
package/dist/use-wc.d.mts CHANGED
@@ -984,4 +984,38 @@ declare global {
984
984
  }
985
985
  }
986
986
  //#endregion
987
- export { UseCalendarBase, UseCalendarRenderDay, UseDateInput, UseDatePicker, UseDatetimeInput, UseDropdown, UseDurationInput, UseFocusgroup, UseListboxInput, UseMenu, UseMonthPicker, UseMonthPickerRenderMonth, UseOption, UseScrollarea, UseSelectInput, UseTimeInput, UseTree, UseTreeitem, UseWeekPicker, UseWidget };
987
+ //#region src/elements/use-intl-datetime/use-intl-datetime.d.ts
988
+ /**
989
+ * Displays a localized, human-readable representation of a date, time, or datetime.
990
+ * Renders a semantic `<time>` element in its shadow root with a machine-readable
991
+ * `datetime` attribute and formatted inner text.
992
+ *
993
+ * Set `datestyle`, `timestyle`, or both to control what is formatted and how.
994
+ * The presence of each attribute determines the format mode:
995
+ * - `datestyle` only → date formatting
996
+ * - `timestyle` only → time formatting
997
+ * - both → date and time formatting
998
+ *
999
+ * Locale is resolved from the nearest ancestor `[lang]` attribute, or
1000
+ * `navigator.language` if none is found. Set `lang` directly on the element to override.
1001
+ *
1002
+ * @attr {string} value - ISO date/time string or Unix timestamp (ms)
1003
+ * @attr {string} datestyle - Date format style: `short` | `medium` | `long` | `full`
1004
+ * @attr {string} timestyle - Time format style: `short` | `medium` | `long` | `full`
1005
+ * @attr {string} lang - BCP 47 locale tag. Inherits from nearest ancestor `[lang]` if not set.
1006
+ */
1007
+ declare class UseIntlDatetime extends UseLocaleElement {
1008
+ #private;
1009
+ static styles: lit.CSSResult;
1010
+ value?: string;
1011
+ datestyle?: string;
1012
+ timestyle?: string;
1013
+ render(): TemplateResult$1<1>;
1014
+ }
1015
+ declare global {
1016
+ interface HTMLElementTagNameMap {
1017
+ "use-intl-datetime": UseIntlDatetime;
1018
+ }
1019
+ }
1020
+ //#endregion
1021
+ export { UseCalendarBase, UseCalendarRenderDay, UseDateInput, UseDatePicker, UseDatetimeInput, UseDropdown, UseDurationInput, UseFocusgroup, UseIntlDatetime, UseListboxInput, UseMenu, UseMonthPicker, UseMonthPickerRenderMonth, UseOption, UseScrollarea, UseSelectInput, UseTimeInput, UseTree, UseTreeitem, UseWeekPicker, UseWidget };
package/dist/use-wc.mjs CHANGED
@@ -672,7 +672,9 @@ let UseDropdown = class UseDropdown extends LitElement {
672
672
  >
673
673
  <slot name="trigger-content">
674
674
  <slot part="trigger-label" name="trigger-label">${this.label}</slot>
675
- <slot part="trigger-icon" name="trigger-icon">${this.#triggerIconText}</slot>
675
+ <slot part="trigger-icon" name="trigger-icon">
676
+ <span part="trigger-icon-default" aria-hidden="true">${this.#triggerIconText}</span>
677
+ </slot>
676
678
  </slot>
677
679
  </button>
678
680
  <div
@@ -1068,6 +1070,13 @@ let UseListboxInput = class UseListboxInput extends LitElement {
1068
1070
  get value() {
1069
1071
  return this.#value;
1070
1072
  }
1073
+ #handleMouseOver(event) {
1074
+ const option = event.target?.closest("use-option");
1075
+ if (option && !option.disabled) this.activeOption = option;
1076
+ }
1077
+ #handleFocus() {
1078
+ if (!this.activeOption) this.activeOption = this.firstSelected ?? this.options.at(0) ?? null;
1079
+ }
1071
1080
  #handleKeyDown(event) {
1072
1081
  if (this.disabled) return;
1073
1082
  if (["Enter", " "].includes(event.key) && this.activeOption) {
@@ -1083,12 +1092,12 @@ let UseListboxInput = class UseListboxInput extends LitElement {
1083
1092
  case "ArrowUp":
1084
1093
  event.preventDefault();
1085
1094
  event.stopPropagation();
1086
- if (activeIndex > 0) moveTo = options.at(activeIndex - 1);
1095
+ moveTo = activeIndex > 0 ? options.at(activeIndex - 1) : options.at(-1);
1087
1096
  break;
1088
1097
  case "ArrowDown":
1089
1098
  event.preventDefault();
1090
1099
  event.stopPropagation();
1091
- moveTo = options.at(activeIndex + 1);
1100
+ moveTo = activeIndex < options.length - 1 ? options.at(activeIndex + 1) : options.at(0);
1092
1101
  break;
1093
1102
  case "Home":
1094
1103
  event.preventDefault();
@@ -1111,6 +1120,8 @@ let UseListboxInput = class UseListboxInput extends LitElement {
1111
1120
  tabindex=${0}
1112
1121
  @click=${this.#handleClick}
1113
1122
  @keydown=${this.#handleKeyDown}
1123
+ @focus=${this.#handleFocus}
1124
+ @mouseover=${this.#handleMouseOver}
1114
1125
  >
1115
1126
  <slot></slot>
1116
1127
  </div>
@@ -1131,9 +1142,7 @@ let UseListboxInput = class UseListboxInput extends LitElement {
1131
1142
  opacity: 0.5;
1132
1143
  }
1133
1144
 
1134
- /* https://github.com/w3c/csswg-drafts/issues/5893 */
1135
- [part="listbox"]:not(:hover):focus-visible ::slotted(use-option:state(active)),
1136
- ::slotted(use-option:not(:state(disabled)):hover) {
1145
+ ::slotted(use-option:state(active)) {
1137
1146
  background-color: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1));
1138
1147
  }
1139
1148
  `;
@@ -4171,4 +4180,94 @@ let UseScrollarea = class UseScrollarea extends LitElement {
4171
4180
  };
4172
4181
  UseScrollarea = __decorate([customElement("use-scrollarea")], UseScrollarea);
4173
4182
  //#endregion
4174
- export { UseCalendarBase, UseDateInput, UseDatePicker, UseDatetimeInput, UseDropdown, UseDurationInput, UseFocusgroup, UseListboxInput, UseMenu, UseMonthPicker, UseOption, UseScrollarea, UseSelectInput, UseTimeInput, UseTree, UseTreeitem, UseWeekPicker, UseWidget };
4183
+ //#region src/elements/use-intl-datetime/use-intl-datetime.ts
4184
+ const DATE_TIME_STYLES = [
4185
+ "short",
4186
+ "medium",
4187
+ "long",
4188
+ "full"
4189
+ ];
4190
+ const TIME_PATTERN = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.\d+)?)?$/;
4191
+ let UseIntlDatetime = class UseIntlDatetime extends UseLocaleElement {
4192
+ static {
4193
+ this.styles = css`
4194
+ :host {
4195
+ display: contents;
4196
+ }
4197
+ `;
4198
+ }
4199
+ #parseDate(value) {
4200
+ if (!value) return null;
4201
+ const asNumber = Number(value);
4202
+ if (!isNaN(asNumber) && value.trim() !== "") return new Date(asNumber);
4203
+ const parsedDate = new Date(value);
4204
+ return isNaN(parsedDate.getTime()) ? null : parsedDate;
4205
+ }
4206
+ #resolveDateStyle() {
4207
+ return DATE_TIME_STYLES.includes(this.datestyle) ? this.datestyle : "medium";
4208
+ }
4209
+ #resolveTimeStyle() {
4210
+ return DATE_TIME_STYLES.includes(this.timestyle) ? this.timestyle : "medium";
4211
+ }
4212
+ #computeFormatted() {
4213
+ const value = this.value ?? "";
4214
+ const locale = this.lang;
4215
+ const hasDateStyle = this.datestyle !== void 0;
4216
+ const hasTimeStyle = this.timestyle !== void 0;
4217
+ if (!value || !hasDateStyle && !hasTimeStyle) return null;
4218
+ try {
4219
+ if (hasDateStyle && !hasTimeStyle) {
4220
+ const parsedDate = this.#parseDate(value);
4221
+ if (!parsedDate) return null;
4222
+ return {
4223
+ datetimeAttr: parsedDate.toISOString().split("T")[0],
4224
+ text: new Intl.DateTimeFormat(locale, { dateStyle: this.#resolveDateStyle() }).format(parsedDate)
4225
+ };
4226
+ }
4227
+ if (hasTimeStyle && !hasDateStyle) {
4228
+ const timeMatch = TIME_PATTERN.exec(value);
4229
+ let parsedDate;
4230
+ let datetimeAttr;
4231
+ if (timeMatch) {
4232
+ const hours = timeMatch[1];
4233
+ const minutes = timeMatch[2];
4234
+ const seconds = timeMatch[3] ?? "00";
4235
+ parsedDate = /* @__PURE__ */ new Date();
4236
+ parsedDate.setHours(parseInt(hours, 10), parseInt(minutes, 10), parseInt(seconds, 10), 0);
4237
+ datetimeAttr = `${hours}:${minutes}:${seconds}`;
4238
+ } else {
4239
+ const fromTimestamp = this.#parseDate(value);
4240
+ if (!fromTimestamp) return null;
4241
+ parsedDate = fromTimestamp;
4242
+ datetimeAttr = `${String(parsedDate.getHours()).padStart(2, "0")}:${String(parsedDate.getMinutes()).padStart(2, "0")}:${String(parsedDate.getSeconds()).padStart(2, "0")}`;
4243
+ }
4244
+ return {
4245
+ datetimeAttr,
4246
+ text: new Intl.DateTimeFormat(locale, { timeStyle: this.#resolveTimeStyle() }).format(parsedDate)
4247
+ };
4248
+ }
4249
+ const parsedDate = this.#parseDate(value);
4250
+ if (!parsedDate) return null;
4251
+ return {
4252
+ datetimeAttr: parsedDate.toISOString(),
4253
+ text: new Intl.DateTimeFormat(locale, {
4254
+ dateStyle: this.#resolveDateStyle(),
4255
+ timeStyle: this.#resolveTimeStyle()
4256
+ }).format(parsedDate)
4257
+ };
4258
+ } catch {
4259
+ return null;
4260
+ }
4261
+ }
4262
+ render() {
4263
+ const result = this.#computeFormatted();
4264
+ if (!result) return html`<time></time>`;
4265
+ return html`<time datetime=${result.datetimeAttr}>${result.text}</time>`;
4266
+ }
4267
+ };
4268
+ __decorate([property({ type: String })], UseIntlDatetime.prototype, "value", void 0);
4269
+ __decorate([property({ type: String })], UseIntlDatetime.prototype, "datestyle", void 0);
4270
+ __decorate([property({ type: String })], UseIntlDatetime.prototype, "timestyle", void 0);
4271
+ UseIntlDatetime = __decorate([customElement("use-intl-datetime")], UseIntlDatetime);
4272
+ //#endregion
4273
+ export { UseCalendarBase, UseDateInput, UseDatePicker, UseDatetimeInput, UseDropdown, UseDurationInput, UseFocusgroup, UseIntlDatetime, UseListboxInput, UseMenu, UseMonthPicker, UseOption, UseScrollarea, UseSelectInput, UseTimeInput, UseTree, UseTreeitem, UseWeekPicker, UseWidget };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "use-wc",
3
- "version": "1.0.0-pre.33",
3
+ "version": "1.0.0-pre.35",
4
4
  "private": false,
5
5
  "homepage": "https://usewc.com",
6
6
  "bugs": "https://github.com/dang-rabbits/use-wc/issues",
@@ -2,6 +2,12 @@
2
2
  "$schema": "https://raw.githubusercontent.com/microsoft/vscode-html-languageservice/main/docs/customData.schema.json",
3
3
  "version": 1.1,
4
4
  "tags": [
5
+ {
6
+ "name": "use-calendarday",
7
+ "description": "A helper component for customizing specific days within `use-calendar`.\nContent placed inside this element will replace the default day number display.\n---\n\n\n### **Slots:**\n - **default** - slot for custom day content (replaces the day number)",
8
+ "attributes": [{ "name": "date", "values": [] }],
9
+ "references": []
10
+ },
5
11
  {
6
12
  "name": "use-date-input",
7
13
  "description": "Displays a date picker using segmented inputs for year, month, and day.\n\nUses browser locale for formatting and ARIA labels.\n---\n",
@@ -13,12 +19,6 @@
13
19
  ],
14
20
  "references": []
15
21
  },
16
- {
17
- "name": "use-calendarday",
18
- "description": "A helper component for customizing specific days within `use-calendar`.\nContent placed inside this element will replace the default day number display.\n---\n\n\n### **Slots:**\n - **default** - slot for custom day content (replaces the day number)",
19
- "attributes": [{ "name": "date", "values": [] }],
20
- "references": []
21
- },
22
22
  {
23
23
  "name": "use-date-picker",
24
24
  "description": "A day-granularity date picker. Value format: YYYY-MM-DD.\n---\n\n\n### **Events:**\n - **use-change** - Fired on selection with detail `{ value: string }`\n\n### **Slots:**\n - **header-start** - Content before the title in the header\n- **title** - Title showing the month and year\n- **controls** - Navigation controls (previous, today, next buttons)\n- **header-end** - Content after the controls in the header\n- **date-{YYYY-MM-DD}** - Per-date content that replaces the default day number\n\n### **CSS Parts:**\n - **header** - The header container\n- **title** - The title text\n- **title-month** - The month part of the title\n- **title-literal** - Literal text in the title\n- **title-year** - The year part of the title\n- **controls** - The controls slot container\n- **control** - Individual control button\n- **control-previous** - Previous month button\n- **control-today** - Today button\n- **control-next** - Next month button\n- **grid** - The main calendar grid\n- **grid-header** - The header row with day names\n- **grid-header-cell** - Individual day name header cell\n- **grid-body** - The container for calendar weeks\n- **row** - A row of days\n- **day** - A day cell\n- **day-empty** - An empty day cell (from previous/next month)\n- **day-selected** - A selected day cell\n- **day-today** - The current date cell\n- **day-disabled** - A disabled date cell\n- **title-button** - The clickable button wrapping the month/year title\n- **picker** - The scrollable month/year picker panel (replaces grid when open)\n- **picker-year-section** - Container for one year's label and month grid\n- **picker-year-label** - The year heading inside a year section\n- **picker-months** - The 4-column month grid inside a year section\n- **picker-month** - An individual month button\n- **picker-month-current** - Applied to the currently selected month button",
@@ -178,6 +178,33 @@
178
178
  ],
179
179
  "references": []
180
180
  },
181
+ {
182
+ "name": "use-intl-datetime",
183
+ "description": "Displays a localized, human-readable representation of a date, time, or datetime.\nRenders a semantic `<time>` element in its shadow root with a machine-readable\n`datetime` attribute and formatted inner text.\n\nSet `datestyle`, `timestyle`, or both to control what is formatted and how.\nThe presence of each attribute determines the format mode:\n- `datestyle` only → date formatting\n- `timestyle` only → time formatting\n- both → date and time formatting\n\nLocale is resolved from the nearest ancestor `[lang]` attribute, or\n`navigator.language` if none is found. Set `lang` directly on the element to override.\n---\n",
184
+ "attributes": [
185
+ {
186
+ "name": "value",
187
+ "description": "ISO date/time string or Unix timestamp (ms)",
188
+ "values": []
189
+ },
190
+ {
191
+ "name": "datestyle",
192
+ "description": "Date format style: `short` | `medium` | `long` | `full`",
193
+ "values": []
194
+ },
195
+ {
196
+ "name": "timestyle",
197
+ "description": "Time format style: `short` | `medium` | `long` | `full`",
198
+ "values": []
199
+ },
200
+ {
201
+ "name": "lang",
202
+ "description": "BCP 47 locale tag. Inherits from nearest ancestor `[lang]` if not set.",
203
+ "values": []
204
+ }
205
+ ],
206
+ "references": []
207
+ },
181
208
  {
182
209
  "name": "use-listbox-input",
183
210
  "description": "\n---\n\n\n### **Events:**\n - **use-change**\n\n### **Slots:**\n - **default** - NodeList of `use-option` elements\n- **arrow** - undefined",