luxen-ui 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/cdn/chunks/decorate.js +1 -1
  2. package/cdn/chunks/decorate.js.map +1 -1
  3. package/cdn/custom-elements.json +131 -107
  4. package/cdn/elements/avatar/avatar.js +1 -1
  5. package/cdn/elements/avatar/avatar.js.map +1 -1
  6. package/cdn/elements/badge/badge.js +1 -1
  7. package/cdn/elements/carousel/carousel.d.ts +9 -1
  8. package/cdn/elements/carousel/carousel.d.ts.map +1 -1
  9. package/cdn/elements/carousel/carousel.js +21 -20
  10. package/cdn/elements/carousel/carousel.js.map +1 -1
  11. package/cdn/elements/dialog/dialog.js +1 -1
  12. package/cdn/elements/divider/divider.js +1 -1
  13. package/cdn/elements/drawer/drawer.js +1 -1
  14. package/cdn/elements/dropdown/dropdown.d.ts +5 -2
  15. package/cdn/elements/dropdown/dropdown.d.ts.map +1 -1
  16. package/cdn/elements/dropdown/dropdown.js +6 -3
  17. package/cdn/elements/dropdown/dropdown.js.map +1 -1
  18. package/cdn/elements/dropdown-item/dropdown-item.js +1 -1
  19. package/cdn/elements/dropdown-item/dropdown-item.js.map +1 -1
  20. package/cdn/elements/icon/icon.js +1 -1
  21. package/cdn/elements/input-otp/input-otp.js +1 -1
  22. package/cdn/elements/input-stepper/input-stepper.js +1 -1
  23. package/cdn/elements/popover/popover.js +1 -1
  24. package/cdn/elements/popover/popover.js.map +1 -1
  25. package/cdn/elements/rating/rating.js +1 -1
  26. package/cdn/elements/tabs/tabs.js +1 -1
  27. package/cdn/elements/toast/toast.js +1 -1
  28. package/cdn/elements/toast/toast.js.map +1 -1
  29. package/cdn/elements/tooltip/tooltip.d.ts +3 -3
  30. package/cdn/elements/tooltip/tooltip.js +1 -1
  31. package/cdn/elements/tooltip/tooltip.js.map +1 -1
  32. package/cdn/elements/tree/tree.js +1 -1
  33. package/cdn/elements/tree/tree.js.map +1 -1
  34. package/cdn/elements/tree-item/tree-item.js +1 -1
  35. package/cdn/elements/tree-item/tree-item.js.map +1 -1
  36. package/cdn/shared/luxen-form-associated-element.js +1 -1
  37. package/cdn/styles/elements/divider.css +7 -0
  38. package/cdn/styles/elements/select.css +3 -3
  39. package/dist/css/elements/divider.css +7 -0
  40. package/dist/css/elements/select.css +3 -3
  41. package/dist/custom-elements.json +131 -107
  42. package/dist/elements/avatar/avatar.css +13 -7
  43. package/dist/elements/carousel/carousel.css +7 -0
  44. package/dist/elements/carousel/carousel.d.ts +9 -1
  45. package/dist/elements/carousel/carousel.d.ts.map +1 -1
  46. package/dist/elements/carousel/carousel.js +71 -37
  47. package/dist/elements/dropdown/dropdown.css +14 -3
  48. package/dist/elements/dropdown/dropdown.d.ts +5 -2
  49. package/dist/elements/dropdown/dropdown.d.ts.map +1 -1
  50. package/dist/elements/dropdown/dropdown.js +19 -7
  51. package/dist/elements/tooltip/tooltip.css +15 -7
  52. package/dist/elements/tooltip/tooltip.d.ts +3 -3
  53. package/dist/elements/tooltip/tooltip.js +3 -3
  54. package/dist/skills/luxen-ui/references/select.md +1 -1
  55. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["../../../src/html/elements/carousel/carousel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG1E,KAAK,cAAc,GAAG,GAAG,GAAG,GAAG,CAAC;AAChC,KAAK,mBAAmB,GACpB,OAAO,GACP,QAAQ,GACR,KAAK,GACL,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;AACpE,KAAK,wBAAwB,GAAG,MAAM,GAAG,MAAM,CAAC;AAChD,KAAK,uBAAuB,GAAG,WAAW,GAAG,WAAW,GAAG,KAAK,CAAC;AAEjE,OAAO,EAAmB,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAGhF,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAM1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAgB,MAAM,EAAE,cAAc,CAAwB;IAE9D,KAAK,EAAG,iBAAiB,CAAC;IAE1B;;OAEG;IAEH,QAAQ,CAAC,QAAQ,SAAK;IAEtB;;;;OAIG;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC;IAE9B;;;;OAIG;IAEH,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAO;IAEpC;;;;OAIG;IAEH,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAW;IAE9C;;OAEG;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAM;IAE/B;;;;OAIG;IAEH,QAAQ,CAAC,IAAI,UAAS;IAEtB;;;;OAIG;IAEH,QAAQ,CAAC,QAAQ,UAAS;IAE1B;;;;OAIG;IAEH,QAAQ,CAAC,QAAQ,SAAM;IAEvB;;;;OAIG;IAEH,QAAQ,CAAC,SAAS,UAAS;IAE3B;;;;OAIG;IAEH,QAAQ,CAAC,cAAc,EAAE,wBAAwB,CAAK;IAEtD;;;;OAIG;IAEH,QAAQ,CAAC,UAAU,SAAK;IAExB;;;;OAIG;IAEH,QAAQ,CAAC,aAAa,EAAE,uBAAuB,CAAe;IAG9D,QAAQ,CAAC,MAAM,UAAS;IAGxB,QAAQ,CAAC,QAAQ,UAAS;IAG1B,QAAQ,CAAC,aAAa,UAAS;IAG/B,QAAQ,CAAC,cAAc,UAAS;IAGhC,QAAQ,CAAC,aAAa,EAAE,QAAQ,GAAG,KAAK,CAAS;IAGjD,QAAQ,CAAC,qBAAqB,EAAE,QAAQ,GAAG,SAAS,CAAY;IAEtC,aAAa,EAAG,WAAW,CAAC;IAC3B,WAAW,EAAG,iBAAiB,CAAC;IACpC,OAAO,EAAG,iBAAiB,CAAC;IAC9B,SAAS,EAAG,eAAe,CAAC;IAC/B,QAAQ,EAAG,iBAAiB,EAAE,CAAC;;IAcxC,iBAAiB,IAAI,IAAI;IAKzB,oBAAoB;cAOV,YAAY,IAAI,IAAI;IAIvC,SAAS,CAAC,WAAW;IAWrB,SAAS,CAAC,cAAc;IAMxB,SAAS,CAAC,MAAM;IAIhB,SAAS,CAAC,QAAQ;IAKlB,SAAS,CAAC,QAAQ;IAOlB,SAAS,CAAC,QAAQ;IAIlB,SAAS,CAAC,oBAAoB;IAK9B,SAAS,CAAC,oBAAoB;IAK9B,SAAS,CAAC,gBAAgB;IAiBX,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,IAAI,CAAC;IAM9D,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,cAAc;IAKtB,OAAO,IAAI,gBAAgB;IA0B3B,IAAI;IAIJ,QAAQ;IAIR,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;IAIvC,UAAU;IAIV,YAAY;IAIZ,QAAQ;IAIR,sBAAsB;IAoBtB,yBAAyB;IAyChB,MAAM;CAuChB"}
1
+ {"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["../../../src/html/elements/carousel/carousel.ts"],"names":[],"mappings":"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"}
@@ -15,11 +15,11 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
15
15
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
16
16
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
17
17
  };
18
- var _LuxenCarousel_autoplay_accessor_storage, _LuxenCarousel_autoplayOptions_accessor_storage, _LuxenCarousel_axis_accessor_storage, _LuxenCarousel_align_accessor_storage, _LuxenCarousel_breakpoints_accessor_storage, _LuxenCarousel_loop_accessor_storage, _LuxenCarousel_dragFree_accessor_storage, _LuxenCarousel_duration_accessor_storage, _LuxenCarousel_skipSnaps_accessor_storage, _LuxenCarousel_slidesToScroll_accessor_storage, _LuxenCarousel_startIndex_accessor_storage, _LuxenCarousel_containScroll_accessor_storage, _LuxenCarousel_single_accessor_storage, _LuxenCarousel_withDots_accessor_storage, _LuxenCarousel_withScrollbar_accessor_storage, _LuxenCarousel_withFullscreen_accessor_storage, _LuxenCarousel_dotAppearance_accessor_storage, _LuxenCarousel_scrollButtonsPosition_accessor_storage;
18
+ var _LuxenCarousel_autoplay_accessor_storage, _LuxenCarousel_autoplayOptions_accessor_storage, _LuxenCarousel_axis_accessor_storage, _LuxenCarousel_align_accessor_storage, _LuxenCarousel_breakpoints_accessor_storage, _LuxenCarousel_loop_accessor_storage, _LuxenCarousel_dragFree_accessor_storage, _LuxenCarousel_duration_accessor_storage, _LuxenCarousel_skipSnaps_accessor_storage, _LuxenCarousel_slidesToScroll_accessor_storage, _LuxenCarousel_startIndex_accessor_storage, _LuxenCarousel_containScroll_accessor_storage, _LuxenCarousel_single_accessor_storage, _LuxenCarousel_withDots_accessor_storage, _LuxenCarousel_withScrollbar_accessor_storage, _LuxenCarousel_withFullscreen_accessor_storage, _LuxenCarousel_dotAppearance_accessor_storage, _LuxenCarousel_maxVisibleDots_accessor_storage, _LuxenCarousel_scrollButtonsPosition_accessor_storage, _LuxenCarousel__selectedSnap_accessor_storage;
19
19
  import EmblaCarousel from 'embla-carousel';
20
20
  import Autoplay from 'embla-carousel-autoplay';
21
- import { html, unsafeCSS } from 'lit';
22
- import { property, query, queryAll } from 'lit/decorators.js';
21
+ import { html, nothing, unsafeCSS } from 'lit';
22
+ import { property, query, state } from 'lit/decorators.js';
23
23
  import { map } from 'lit/directives/map.js';
24
24
  import { LuxenElement } from '../../shared/luxen-element';
25
25
  import hostStyles from '../../shared/styles/host.styles';
@@ -53,6 +53,7 @@ const styles = unsafeCSS(rawStyles);
53
53
  * @cssproperty --dot-color - Color of inactive dots.
54
54
  * @cssproperty --dot-color-active - Color of active dot.
55
55
  * @cssproperty --dot-margin - Margin around dots container.
56
+ * @cssproperty --dot-edge-scale - Scale factor applied to edge dots that signal more dots exist beyond the visible window (default `0.5`).
56
57
  */
57
58
  export class LuxenCarousel extends LuxenElement {
58
59
  /**
@@ -145,8 +146,17 @@ export class LuxenCarousel extends LuxenElement {
145
146
  set withFullscreen(value) { __classPrivateFieldSet(this, _LuxenCarousel_withFullscreen_accessor_storage, value, "f"); }
146
147
  get dotAppearance() { return __classPrivateFieldGet(this, _LuxenCarousel_dotAppearance_accessor_storage, "f"); }
147
148
  set dotAppearance(value) { __classPrivateFieldSet(this, _LuxenCarousel_dotAppearance_accessor_storage, value, "f"); }
149
+ /**
150
+ * Maximum number of dots rendered at once. When the snap count exceeds this,
151
+ * a sliding window keeps the active dot in view and shrinks the edge dot(s)
152
+ * on the side where dots are hidden. `0` (default) renders all dots.
153
+ */
154
+ get maxVisibleDots() { return __classPrivateFieldGet(this, _LuxenCarousel_maxVisibleDots_accessor_storage, "f"); }
155
+ set maxVisibleDots(value) { __classPrivateFieldSet(this, _LuxenCarousel_maxVisibleDots_accessor_storage, value, "f"); }
148
156
  get scrollButtonsPosition() { return __classPrivateFieldGet(this, _LuxenCarousel_scrollButtonsPosition_accessor_storage, "f"); }
149
157
  set scrollButtonsPosition(value) { __classPrivateFieldSet(this, _LuxenCarousel_scrollButtonsPosition_accessor_storage, value, "f"); }
158
+ get _selectedSnap() { return __classPrivateFieldGet(this, _LuxenCarousel__selectedSnap_accessor_storage, "f"); }
159
+ set _selectedSnap(value) { __classPrivateFieldSet(this, _LuxenCarousel__selectedSnap_accessor_storage, value, "f"); }
150
160
  constructor() {
151
161
  super();
152
162
  _LuxenCarousel_autoplay_accessor_storage.set(this, 0);
@@ -166,7 +176,9 @@ export class LuxenCarousel extends LuxenElement {
166
176
  _LuxenCarousel_withScrollbar_accessor_storage.set(this, false);
167
177
  _LuxenCarousel_withFullscreen_accessor_storage.set(this, false);
168
178
  _LuxenCarousel_dotAppearance_accessor_storage.set(this, 'bar');
179
+ _LuxenCarousel_maxVisibleDots_accessor_storage.set(this, 0);
169
180
  _LuxenCarousel_scrollButtonsPosition_accessor_storage.set(this, 'inside');
181
+ _LuxenCarousel__selectedSnap_accessor_storage.set(this, 0);
170
182
  this.next = this.next.bind(this);
171
183
  this.previous = this.previous.bind(this);
172
184
  this.onInit = this.onInit.bind(this);
@@ -233,14 +245,7 @@ export class LuxenCarousel extends LuxenElement {
233
245
  this.previousBtn.toggleAttribute('disabled', !this.embla.canScrollPrev());
234
246
  this.nextBtn.toggleAttribute('disabled', !this.embla.canScrollNext());
235
247
  this.scrollButtons.classList.toggle('scroll-buttons--disabled', !canScroll);
236
- if (this.withDots) {
237
- const previous = this.embla.previousScrollSnap();
238
- const selected = this.embla.selectedScrollSnap();
239
- this.dotNodes[previous]?.classList.remove('dot--selected');
240
- this.dotNodes[previous]?.removeAttribute('aria-selected');
241
- this.dotNodes[selected]?.classList.add('dot--selected');
242
- this.dotNodes[selected]?.setAttribute('aria-selected', 'true');
243
- }
248
+ this._selectedSnap = this.embla.selectedScrollSnap();
244
249
  }
245
250
  async updated(changedProperties) {
246
251
  if (changedProperties.has('autoplay') && this.autoplay) {
@@ -360,6 +365,53 @@ export class LuxenCarousel extends LuxenElement {
360
365
  </button>
361
366
  </div>`;
362
367
  }
368
+ renderDots() {
369
+ if (!this.embla)
370
+ return nothing;
371
+ const snaps = this.embla.scrollSnapList();
372
+ const total = snaps.length;
373
+ if (total === 0)
374
+ return nothing;
375
+ const selected = this._selectedSnap;
376
+ const max = this.maxVisibleDots;
377
+ let start = 0;
378
+ let end = total;
379
+ if (max > 0 && max < total) {
380
+ const half = Math.floor((max - 1) / 2);
381
+ start = Math.max(0, selected - half);
382
+ end = Math.min(total, start + max);
383
+ if (end - start < max)
384
+ start = Math.max(0, end - max);
385
+ }
386
+ const edgeStart = start > 0;
387
+ const edgeEnd = end < total;
388
+ return html `<div
389
+ class="dots"
390
+ part="dots"
391
+ role="tablist"
392
+ >
393
+ ${map(snaps.slice(start, end), (_, i) => {
394
+ const index = start + i;
395
+ const isFirst = i === 0;
396
+ const isLast = i === end - start - 1;
397
+ const isSelected = index === selected;
398
+ const isEdge = !isSelected && ((isFirst && edgeStart) || (isLast && edgeEnd));
399
+ return html `<button
400
+ part="button-dot"
401
+ type="button"
402
+ role="tab"
403
+ class="dot dot--${this.dotAppearance} ${isSelected ? 'dot--selected' : ''}"
404
+ aria-label="Go to slide ${index + 1}"
405
+ aria-selected=${isSelected ? 'true' : nothing}
406
+ data-index="${index}"
407
+ data-edge=${isEdge ? '' : nothing}
408
+ @click=${this.handleDotClick}
409
+ >
410
+ <i></i>
411
+ </button>`;
412
+ })}
413
+ </div>`;
414
+ }
363
415
  render() {
364
416
  return html `
365
417
  <div class="wrapper ${this.isActive() ? '' : 'inactive'}">
@@ -374,33 +426,12 @@ export class LuxenCarousel extends LuxenElement {
374
426
  ></slot>
375
427
  </div>
376
428
  ${this.withFullscreen ? this.renderFullscreenButton() : ''}
377
- ${this.renderNextPreviousButtons()}
378
- ${this.withDots
379
- ? html `<div
380
- class="dots"
381
- part="dots"
382
- role="tablist"
383
- >
384
- ${map(this.embla.scrollSnapList(), (_, index) => {
385
- return html `<button
386
- part="button-dot"
387
- type="button"
388
- role="tab"
389
- class="dot dot--${this.dotAppearance}"
390
- aria-label="Go to slide ${index + 1}"
391
- data-index="${index}"
392
- @click=${this.handleDotClick}
393
- >
394
- <i></i>
395
- </button>`;
396
- })}
397
- </div> `
398
- : ''}
429
+ ${this.renderNextPreviousButtons()} ${this.withDots ? this.renderDots() : ''}
399
430
  </div>
400
431
  `;
401
432
  }
402
433
  }
403
- _LuxenCarousel_autoplay_accessor_storage = new WeakMap(), _LuxenCarousel_autoplayOptions_accessor_storage = new WeakMap(), _LuxenCarousel_axis_accessor_storage = new WeakMap(), _LuxenCarousel_align_accessor_storage = new WeakMap(), _LuxenCarousel_breakpoints_accessor_storage = new WeakMap(), _LuxenCarousel_loop_accessor_storage = new WeakMap(), _LuxenCarousel_dragFree_accessor_storage = new WeakMap(), _LuxenCarousel_duration_accessor_storage = new WeakMap(), _LuxenCarousel_skipSnaps_accessor_storage = new WeakMap(), _LuxenCarousel_slidesToScroll_accessor_storage = new WeakMap(), _LuxenCarousel_startIndex_accessor_storage = new WeakMap(), _LuxenCarousel_containScroll_accessor_storage = new WeakMap(), _LuxenCarousel_single_accessor_storage = new WeakMap(), _LuxenCarousel_withDots_accessor_storage = new WeakMap(), _LuxenCarousel_withScrollbar_accessor_storage = new WeakMap(), _LuxenCarousel_withFullscreen_accessor_storage = new WeakMap(), _LuxenCarousel_dotAppearance_accessor_storage = new WeakMap(), _LuxenCarousel_scrollButtonsPosition_accessor_storage = new WeakMap();
434
+ _LuxenCarousel_autoplay_accessor_storage = new WeakMap(), _LuxenCarousel_autoplayOptions_accessor_storage = new WeakMap(), _LuxenCarousel_axis_accessor_storage = new WeakMap(), _LuxenCarousel_align_accessor_storage = new WeakMap(), _LuxenCarousel_breakpoints_accessor_storage = new WeakMap(), _LuxenCarousel_loop_accessor_storage = new WeakMap(), _LuxenCarousel_dragFree_accessor_storage = new WeakMap(), _LuxenCarousel_duration_accessor_storage = new WeakMap(), _LuxenCarousel_skipSnaps_accessor_storage = new WeakMap(), _LuxenCarousel_slidesToScroll_accessor_storage = new WeakMap(), _LuxenCarousel_startIndex_accessor_storage = new WeakMap(), _LuxenCarousel_containScroll_accessor_storage = new WeakMap(), _LuxenCarousel_single_accessor_storage = new WeakMap(), _LuxenCarousel_withDots_accessor_storage = new WeakMap(), _LuxenCarousel_withScrollbar_accessor_storage = new WeakMap(), _LuxenCarousel_withFullscreen_accessor_storage = new WeakMap(), _LuxenCarousel_dotAppearance_accessor_storage = new WeakMap(), _LuxenCarousel_maxVisibleDots_accessor_storage = new WeakMap(), _LuxenCarousel_scrollButtonsPosition_accessor_storage = new WeakMap(), _LuxenCarousel__selectedSnap_accessor_storage = new WeakMap();
404
435
  LuxenCarousel.styles = [hostStyles, styles];
405
436
  __decorate([
406
437
  property({ type: Number, reflect: true })
@@ -453,9 +484,15 @@ __decorate([
453
484
  __decorate([
454
485
  property({ type: String, attribute: 'dot-appearance' })
455
486
  ], LuxenCarousel.prototype, "dotAppearance", null);
487
+ __decorate([
488
+ property({ type: Number, attribute: 'max-visible-dots' })
489
+ ], LuxenCarousel.prototype, "maxVisibleDots", null);
456
490
  __decorate([
457
491
  property({ type: String, attribute: 'scroll-buttons-position' })
458
492
  ], LuxenCarousel.prototype, "scrollButtonsPosition", null);
493
+ __decorate([
494
+ state()
495
+ ], LuxenCarousel.prototype, "_selectedSnap", null);
459
496
  __decorate([
460
497
  query('.scroll-buttons')
461
498
  ], LuxenCarousel.prototype, "scrollButtons", void 0);
@@ -468,6 +505,3 @@ __decorate([
468
505
  __decorate([
469
506
  query('.container')
470
507
  ], LuxenCarousel.prototype, "container", void 0);
471
- __decorate([
472
- queryAll('.dot')
473
- ], LuxenCarousel.prototype, "dotNodes", void 0);
@@ -1,6 +1,8 @@
1
1
  :host {
2
+ --padding: 0.25rem;
3
+
2
4
  --background: var(--l-color-bg-surface, Canvas);
3
- --radius: 6px;
5
+ --border-radius: 6px;
4
6
  --shadow: 0 4px 6px -1px rgb(0 0 0 / 8%), 0 2px 4px -2px rgb(0 0 0 / 6%);
5
7
  --show-duration: 150;
6
8
  --hide-duration: 150;
@@ -19,13 +21,22 @@
19
21
  box-sizing: border-box;
20
22
  width: max-content;
21
23
  min-width: anchor-size(width);
22
- padding: 0.25rem;
24
+ padding: var(--padding);
23
25
  margin: 0;
24
26
  border: 1px solid var(--l-color-border-overlay, light-dark(#e5e7eb, #374151));
25
- border-radius: var(--radius);
27
+ border-radius: var(--border-radius);
26
28
  background: var(--background);
27
29
  color: var(--l-color-text-primary, CanvasText);
28
30
  box-shadow: var(--shadow);
29
31
  font-size: 0.875rem;
30
32
  line-height: 1.5;
31
33
  }
34
+
35
+ /* Lightweight separator alternative to <l-divider> — same dimensions, no extra import. */
36
+ ::slotted(hr) {
37
+ height: 1px;
38
+ margin-block: var(--padding);
39
+ margin-inline: calc(var(--padding) * -1);
40
+ border: 0;
41
+ background: var(--l-color-divider);
42
+ }
@@ -5,12 +5,15 @@ import type { Placement } from '@floating-ui/dom';
5
5
  * A dropdown menu anchored to a trigger element.
6
6
  *
7
7
  * @slot trigger - The element that triggers the dropdown.
8
- * @slot - Menu content (`l-dropdown-item` elements).
8
+ * @slot header - Optional content rendered above the menu items (e.g. a user profile row). Use an `<l-divider>` (or `<hr>`) after it to separate from items.
9
+ * @slot - Menu content (`l-dropdown-item` elements). Drop an `<l-divider>` (or `<hr>`) between items to render a section separator.
10
+ * @slot footer - Optional content rendered below the menu items (e.g. a version label or shortcut row). Use an `<l-divider>` (or `<hr>`) before it to separate from items.
9
11
  *
10
12
  * @csspart panel - The floating menu container.
11
13
  *
12
14
  * @cssproperty --background - Panel background color.
13
- * @cssproperty --radius - Panel border radius. Default `8px`.
15
+ * @cssproperty --border-radius - Panel border radius. Default `8px`.
16
+ * @cssproperty --padding - Panel inner padding. Default `0.25rem`. Slotted `<l-divider>` elements bleed by this amount on each side to span the panel edges.
14
17
  * @cssproperty --shadow - Panel box shadow.
15
18
  * @cssproperty --show-duration - Show animation duration in ms. Default `150`.
16
19
  * @cssproperty --hide-duration - Hide animation duration in ms. Default `150`.
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown.d.ts","sourceRoot":"","sources":["../../../src/html/elements/dropdown/dropdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AASlD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAgB,MAAM,4BAAwB;IAE9C,OAAO,CAAC,SAAS,CAId;IAEH,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,iBAAiB,CAAK;IAE9B,oCAAoC;IAEpC,QAAQ,CAAC,IAAI,UAAS;IAEtB,wCAAwC;IAExC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAkB;IAE/C,2CAA2C;IAE3C,QAAQ,CAAC,QAAQ,SAAK;IAEtB,qCAAqC;IAErC,QAAQ,CAAC,QAAQ,UAAS;IAE1B,OAAO,KAAK,UAAU,GAGrB;IAED,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,YAAY;IAOpB,IAAI;IAKJ,IAAI;IAKJ,MAAM;IAOG,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;YAQhC,iBAAiB;IAyB/B,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,eAAe,CAErB;IAEF,OAAO,CAAC,iBAAiB,CAYvB;IAEF,OAAO,CAAC,eAAe,CAiCrB;IAEF,OAAO,CAAC,YAAY,CAKlB;IAEF,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,WAAW;IAWnB,2DAA2D;IAC3D,OAAO,CAAC,SAAS,CAMf;IAEO,MAAM;CAqBhB"}
1
+ {"version":3,"file":"dropdown.d.ts","sourceRoot":"","sources":["../../../src/html/elements/dropdown/dropdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AASlD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAgB,MAAM,4BAAwB;IAE9C,OAAO,CAAC,SAAS,CAId;IAEH,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,iBAAiB,CAAK;IAE9B,oCAAoC;IAEpC,QAAQ,CAAC,IAAI,UAAS;IAEtB,wCAAwC;IAExC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAkB;IAE/C,2CAA2C;IAE3C,QAAQ,CAAC,QAAQ,SAAK;IAEtB,qCAAqC;IAErC,QAAQ,CAAC,QAAQ,UAAS;IAE1B,OAAO,KAAK,UAAU,GAGrB;IAED,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,YAAY;IAOpB,IAAI;IAKJ,IAAI;IAKJ,MAAM;IAOG,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;YAQhC,iBAAiB;IAyB/B,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,eAAe,CAQrB;IAEF,OAAO,CAAC,iBAAiB,CAYvB;IAEF,OAAO,CAAC,eAAe,CAiCrB;IAEF,OAAO,CAAC,YAAY,CAKlB;IAEF,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,WAAW;IAWnB,2DAA2D;IAC3D,OAAO,CAAC,SAAS,CAMf;IAEO,MAAM;CAwBhB"}
@@ -28,12 +28,15 @@ const styles = unsafeCSS(rawStyles);
28
28
  * A dropdown menu anchored to a trigger element.
29
29
  *
30
30
  * @slot trigger - The element that triggers the dropdown.
31
- * @slot - Menu content (`l-dropdown-item` elements).
31
+ * @slot header - Optional content rendered above the menu items (e.g. a user profile row). Use an `<l-divider>` (or `<hr>`) after it to separate from items.
32
+ * @slot - Menu content (`l-dropdown-item` elements). Drop an `<l-divider>` (or `<hr>`) between items to render a section separator.
33
+ * @slot footer - Optional content rendered below the menu items (e.g. a version label or shortcut row). Use an `<l-divider>` (or `<hr>`) before it to separate from items.
32
34
  *
33
35
  * @csspart panel - The floating menu container.
34
36
  *
35
37
  * @cssproperty --background - Panel background color.
36
- * @cssproperty --radius - Panel border radius. Default `8px`.
38
+ * @cssproperty --border-radius - Panel border radius. Default `8px`.
39
+ * @cssproperty --padding - Panel inner padding. Default `0.25rem`. Slotted `<l-divider>` elements bleed by this amount on each side to span the panel edges.
37
40
  * @cssproperty --shadow - Panel box shadow.
38
41
  * @cssproperty --show-duration - Show animation duration in ms. Default `150`.
39
42
  * @cssproperty --hide-duration - Hide animation duration in ms. Default `150`.
@@ -59,9 +62,15 @@ export class LuxenDropdown extends LuxenElement {
59
62
  _LuxenDropdown_distance_accessor_storage.set(this, 4);
60
63
  _LuxenDropdown_disabled_accessor_storage.set(this, false);
61
64
  // --- Event handlers ---
62
- this._onTriggerClick = () => {
63
- if (!this.disabled)
64
- this.toggle();
65
+ this._onTriggerClick = (e) => {
66
+ if (this.disabled)
67
+ return;
68
+ this.toggle();
69
+ // Space/Enter on a native button dispatches click with detail=0; focus the
70
+ // first item so the menu is keyboard-navigable immediately on open.
71
+ if (this.open && e.detail === 0) {
72
+ requestAnimationFrame(() => this._focusFirstItem());
73
+ }
65
74
  };
66
75
  this._onTriggerKeyDown = (e) => {
67
76
  if (this.disabled)
@@ -296,12 +305,15 @@ export class LuxenDropdown extends LuxenElement {
296
305
  <div
297
306
  popover="auto"
298
307
  part="panel"
299
- role="menu"
300
308
  @keydown=${this._onPanelKeyDown}
301
309
  @click=${this._onItemClick}
302
310
  @toggle=${this._onToggle}
303
311
  >
304
- <slot></slot>
312
+ <slot name="header"></slot>
313
+ <div role="menu">
314
+ <slot></slot>
315
+ </div>
316
+ <slot name="footer"></slot>
305
317
  </div>
306
318
  `;
307
319
  }
@@ -1,7 +1,6 @@
1
1
  :host {
2
- --background: var(--l-color-bg-fill-brand, light-dark(#1f2937, #f9fafb));
3
- --color: light-dark(#fff, #111827);
4
- --radius: 4px;
2
+ --background-color: var(--l-color-bg-fill-brand, light-dark(#1f2937, #f9fafb));
3
+ --border-radius: 4px;
5
4
  --max-width: 180px;
6
5
  --arrow-size: 6px;
7
6
  --show-duration: 150ms;
@@ -18,20 +17,29 @@
18
17
  max-width: var(--max-width);
19
18
  padding: 4px 8px;
20
19
  border: 0;
21
- border-radius: var(--radius);
22
- background: var(--background);
23
- color: var(--color);
20
+ border-radius: var(--border-radius);
21
+ background: var(--background-color);
22
+ color: var(
23
+ --text-color,
24
+ oklch(from var(--background-color) calc(0.59 - 0.41 * sign(l - 0.5)) 0 0)
25
+ );
24
26
  font-size: 0.8125rem;
25
27
  line-height: 1.4;
26
28
  filter: drop-shadow(0 1px 2px rgb(0 0 0 / 16%));
27
29
  pointer-events: none;
28
30
  }
29
31
 
32
+ @supports (color: contrast-color(red vs black, white)) {
33
+ [popover] {
34
+ color: var(--text-color, contrast-color(var(--background-color) vs #111827, #fff to AA));
35
+ }
36
+ }
37
+
30
38
  i {
31
39
  position: absolute;
32
40
  display: block;
33
41
  width: var(--arrow-size);
34
42
  height: var(--arrow-size);
35
- background: var(--background);
43
+ background: var(--background-color);
36
44
  transform: rotate(45deg);
37
45
  }
@@ -10,9 +10,9 @@ import type { Placement } from '@floating-ui/dom';
10
10
  * @csspart body - The tooltip popover container.
11
11
  * @csspart arrow - The directional arrow element.
12
12
  *
13
- * @cssproperty --background - Background color. Default: dark in light mode, light in dark mode.
14
- * @cssproperty --color - Text color.
15
- * @cssproperty --radius - Border radius. Default `4px`.
13
+ * @cssproperty --background-color - Background color. Default: dark in light mode, light in dark mode.
14
+ * @cssproperty --text-color - Text color. If unset, auto-derived from `--background-color` luminance.
15
+ * @cssproperty --border-radius - Border radius. Default `4px`.
16
16
  * @cssproperty --max-width - Maximum width. Default `180px`.
17
17
  * @cssproperty --arrow-size - Arrow size. Default `6px`.
18
18
  * @cssproperty --show-duration - Show animation duration. Default `150ms`.
@@ -33,9 +33,9 @@ const styles = unsafeCSS(rawStyles);
33
33
  * @csspart body - The tooltip popover container.
34
34
  * @csspart arrow - The directional arrow element.
35
35
  *
36
- * @cssproperty --background - Background color. Default: dark in light mode, light in dark mode.
37
- * @cssproperty --color - Text color.
38
- * @cssproperty --radius - Border radius. Default `4px`.
36
+ * @cssproperty --background-color - Background color. Default: dark in light mode, light in dark mode.
37
+ * @cssproperty --text-color - Text color. If unset, auto-derived from `--background-color` luminance.
38
+ * @cssproperty --border-radius - Border radius. Default `4px`.
39
39
  * @cssproperty --max-width - Maximum width. Default `180px`.
40
40
  * @cssproperty --arrow-size - Arrow size. Default `6px`.
41
41
  * @cssproperty --show-duration - Show animation duration. Default `150ms`.
@@ -95,6 +95,6 @@ Selects are used to pick a single option from a dropdown list. Commonly used in
95
95
  ### CSS custom properties
96
96
 
97
97
  <ApiTable :data="[
98
- { Name: '--radius', Description: 'Border radius (default: 4px)' },
98
+ { Name: '--border-radius', Description: 'Border radius (default: 4px)' },
99
99
  { Name: '--border-color', Description: 'Border color (adapts to light/dark)' },
100
100
  ]" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "luxen-ui",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Modern web components and CSS-first UI library built with Lit. Framework-agnostic, customizable prefix, design tokens.",
5
5
  "keywords": [
6
6
  "custom-elements",