@daikin-oss/design-system-web-components 2.0.1-next.1 → 2.1.0-next.2

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 (63) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/custom-elements.json +229 -42
  3. package/dist/cjs/base/dds-element.cjs +1 -1
  4. package/dist/cjs/components/carousel/daikin-carousel.cjs +298 -57
  5. package/dist/cjs/components/carousel/daikin-carousel.d.cts +50 -7
  6. package/dist/cjs/components/carousel-item/daikin-carousel-item.cjs +18 -2
  7. package/dist/cjs/components/carousel-item/daikin-carousel-item.d.cts +1 -5
  8. package/dist/cjs/components/chip/daikin-chip.cjs +24 -6
  9. package/dist/cjs/components/chip/daikin-chip.d.cts +2 -0
  10. package/dist/cjs/components/combobox/daikin-combobox.cjs +14 -4
  11. package/dist/cjs/components/combobox/daikin-combobox.d.cts +8 -0
  12. package/dist/cjs/components/icon-button/daikin-icon-button.cjs +42 -7
  13. package/dist/cjs/components/tag/daikin-tag.cjs +3 -1
  14. package/dist/cjs/components/text-field/daikin-text-field.cjs +12 -12
  15. package/dist/cjs/controllers/click-outside.cjs +5 -7
  16. package/dist/cjs/controllers/click-outside.d.cts +3 -3
  17. package/dist/cjs/tailwind.css.cjs +1 -1
  18. package/dist/cjs-dev/base/dds-element.cjs +1 -1
  19. package/dist/cjs-dev/components/carousel/daikin-carousel.cjs +300 -59
  20. package/dist/cjs-dev/components/carousel/daikin-carousel.d.cts +50 -7
  21. package/dist/cjs-dev/components/carousel-item/daikin-carousel-item.cjs +18 -2
  22. package/dist/cjs-dev/components/carousel-item/daikin-carousel-item.d.cts +1 -5
  23. package/dist/cjs-dev/components/chip/daikin-chip.cjs +24 -6
  24. package/dist/cjs-dev/components/chip/daikin-chip.d.cts +2 -0
  25. package/dist/cjs-dev/components/combobox/daikin-combobox.cjs +14 -4
  26. package/dist/cjs-dev/components/combobox/daikin-combobox.d.cts +8 -0
  27. package/dist/cjs-dev/components/icon-button/daikin-icon-button.cjs +42 -7
  28. package/dist/cjs-dev/components/tag/daikin-tag.cjs +3 -1
  29. package/dist/cjs-dev/components/text-field/daikin-text-field.cjs +12 -12
  30. package/dist/cjs-dev/controllers/click-outside.cjs +5 -7
  31. package/dist/cjs-dev/controllers/click-outside.d.cts +3 -3
  32. package/dist/cjs-dev/tailwind.css.cjs +1 -1
  33. package/dist/es/base/dds-element.js +1 -1
  34. package/dist/es/components/carousel/daikin-carousel.d.ts +50 -7
  35. package/dist/es/components/carousel/daikin-carousel.js +297 -58
  36. package/dist/es/components/carousel-item/daikin-carousel-item.d.ts +1 -5
  37. package/dist/es/components/carousel-item/daikin-carousel-item.js +18 -2
  38. package/dist/es/components/chip/daikin-chip.d.ts +2 -0
  39. package/dist/es/components/chip/daikin-chip.js +25 -7
  40. package/dist/es/components/combobox/daikin-combobox.d.ts +8 -0
  41. package/dist/es/components/combobox/daikin-combobox.js +14 -4
  42. package/dist/es/components/icon-button/daikin-icon-button.js +42 -7
  43. package/dist/es/components/tag/daikin-tag.js +3 -1
  44. package/dist/es/components/text-field/daikin-text-field.js +12 -12
  45. package/dist/es/controllers/click-outside.d.ts +3 -3
  46. package/dist/es/controllers/click-outside.js +5 -7
  47. package/dist/es/tailwind.css.js +1 -1
  48. package/dist/es-dev/base/dds-element.js +1 -1
  49. package/dist/es-dev/components/carousel/daikin-carousel.d.ts +50 -7
  50. package/dist/es-dev/components/carousel/daikin-carousel.js +299 -60
  51. package/dist/es-dev/components/carousel-item/daikin-carousel-item.d.ts +1 -5
  52. package/dist/es-dev/components/carousel-item/daikin-carousel-item.js +18 -2
  53. package/dist/es-dev/components/chip/daikin-chip.d.ts +2 -0
  54. package/dist/es-dev/components/chip/daikin-chip.js +25 -7
  55. package/dist/es-dev/components/combobox/daikin-combobox.d.ts +8 -0
  56. package/dist/es-dev/components/combobox/daikin-combobox.js +14 -4
  57. package/dist/es-dev/components/icon-button/daikin-icon-button.js +42 -7
  58. package/dist/es-dev/components/tag/daikin-tag.js +3 -1
  59. package/dist/es-dev/components/text-field/daikin-text-field.js +12 -12
  60. package/dist/es-dev/controllers/click-outside.d.ts +3 -3
  61. package/dist/es-dev/controllers/click-outside.js +5 -7
  62. package/dist/es-dev/tailwind.css.js +1 -1
  63. package/package.json +2 -1
@@ -42,7 +42,7 @@ function ensureGlobalKeyIndex(name) {
42
42
  */
43
43
  var DDSElement = class extends lit.LitElement {
44
44
  static {
45
- this.version = "2.0.1-next.1";
45
+ this.version = "2.1.0-next.2";
46
46
  }
47
47
  /**
48
48
  * Override of LitElement's getPropertyDescriptor to add support for fallback values
@@ -1,3 +1,4 @@
1
+ const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
1
2
  const require_dds_element = require("../../base/dds-element.cjs");
2
3
  const require_dds_property = require("../../base/dds-property.cjs");
3
4
  const require_decorate = require("../../_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.cjs");
@@ -10,19 +11,57 @@ let lit_decorators_js = require("lit/decorators.js");
10
11
  let class_variance_authority = require("class-variance-authority");
11
12
  let lit_directives_ref_js = require("lit/directives/ref.js");
12
13
  let lit_directives_repeat_js = require("lit/directives/repeat.js");
14
+ let embla_carousel = require("embla-carousel");
15
+ embla_carousel = require_runtime.__toESM(embla_carousel, 1);
13
16
  //#region src/components/carousel/daikin-carousel.ts
14
- var DEFAULT_TRANSITION_DURATION = "600ms";
15
17
  var cvaButton = (0, class_variance_authority.cva)([
16
18
  "flex",
17
19
  "justify-center",
18
20
  "items-center",
19
21
  "flex-none",
20
- "size-6",
21
22
  "text-current"
22
- ], { variants: { intent: {
23
- previous: ["icon-[daikin--chevron-left]"],
24
- next: ["icon-[daikin--chevron-right]"]
23
+ ], { variants: {
24
+ intent: {
25
+ previous: ["icon-[daikin--chevron-left]"],
26
+ next: ["icon-[daikin--chevron-right]"]
27
+ },
28
+ arrows: {
29
+ outside: ["size-6"],
30
+ inside: ["size-8"]
31
+ }
32
+ } });
33
+ var outsideButtonWrapper = (0, class_variance_authority.cva)([
34
+ "hidden",
35
+ "flex-none",
36
+ "relative",
37
+ "w-6"
38
+ ], { variants: { arrows: {
39
+ outside: ["md:block"],
40
+ inside: ["md:hidden"]
25
41
  } } });
42
+ var insideButtonWrapper = (0, class_variance_authority.cva)([
43
+ "absolute",
44
+ "top-(--ddc-arrow-y,50%)",
45
+ "-translate-y-1/2",
46
+ "z-10",
47
+ "flex"
48
+ ], { variants: {
49
+ arrows: {
50
+ outside: ["md:hidden"],
51
+ inside: ["md:flex"]
52
+ },
53
+ intent: {
54
+ previous: ["left-4"],
55
+ next: ["right-4"]
56
+ }
57
+ } });
58
+ var INJECTION_CLASS_INSIDE_BUTTON = (0, class_variance_authority.cva)([
59
+ "[--ddc-color-common-surface-neutral-default:var(--dds-color-common-surface-overlay-default)]",
60
+ "[--ddc-color-common-surface-neutral-hover:var(--dds-color-common-surface-overlay-hover)]",
61
+ "[--ddc-color-common-surface-neutral-press:var(--dds-color-common-surface-overlay-press)]",
62
+ "[--ddc-color-common-disabled:var(--dds-color-common-surface-overlay-disabled)]",
63
+ "[--ddc-color-common-surface-disabled:var(--dds-color-common-surface-disabled-overlay)]"
64
+ ])();
26
65
  var INDICATOR_CLASS_NAME = (0, class_variance_authority.cva)([
27
66
  "flex",
28
67
  "justify-center",
@@ -45,14 +84,41 @@ var INDICATOR_CLASS_NAME = (0, class_variance_authority.cva)([
45
84
  "aria-selected:focus-visible:after:outline-offset-1",
46
85
  "aria-selected:focus-visible:after:outline-ddt-color-common-border-focus"
47
86
  ])();
87
+ var DEFAULT_EMBLA_DURATION = 25;
88
+ var LEGACY_CSS_DURATION_MS = 600;
89
+ var parseDurationMs = (value) => {
90
+ const matched = value.trim().match(/^(\d+(?:\.\d+)?)(ms|s)$/);
91
+ if (!matched) return void 0;
92
+ const duration = Number(matched[1]);
93
+ return matched[2] === "s" ? duration * 1e3 : duration;
94
+ };
48
95
  var DaikinCarousel = class DaikinCarousel extends require_dds_element.DDSElement {
49
96
  constructor(..._args) {
50
97
  super(..._args);
51
98
  this.currentIndex = 0;
99
+ this.loop = false;
52
100
  this._itemCount = 0;
53
- this._prevButton = (0, lit_directives_ref_js.createRef)();
54
- this._nextButton = (0, lit_directives_ref_js.createRef)();
55
101
  this._indicatorButtonsContainer = (0, lit_directives_ref_js.createRef)();
102
+ this._viewport = (0, lit_directives_ref_js.createRef)();
103
+ this._track = (0, lit_directives_ref_js.createRef)();
104
+ this._isDragging = false;
105
+ this._onEmblaPointerDown = () => {
106
+ this._isDragging = true;
107
+ };
108
+ this._onEmblaSettle = () => {
109
+ this._isDragging = false;
110
+ };
111
+ this._onEmblaSelect = () => {
112
+ if (!this._emblaApi) return;
113
+ const previousIndex = this.currentIndex;
114
+ const newIndex = this._emblaApi.selectedScrollSnap();
115
+ if (previousIndex !== newIndex) {
116
+ this.currentIndex = newIndex;
117
+ this._emitSelect(this._isDragging ? "swipe" : this._pendingOperation ?? "indicator", previousIndex);
118
+ this._updateItemActive();
119
+ }
120
+ this._pendingOperation = void 0;
121
+ };
56
122
  }
57
123
  static {
58
124
  this.styles = lit.css`
@@ -62,21 +128,89 @@ var DaikinCarousel = class DaikinCarousel extends require_dds_element.DDSElement
62
128
  display: block;
63
129
  width: 100%;
64
130
  position: relative;
131
+ /* Defaults to vertical center and is later overridden by ResizeObserver. */
132
+ --ddc-arrow-y: 50%;
133
+ /* Defaults aspect ratio for carousel items */
134
+ --ddc-item-aspect-ratio: 16 / 9;
135
+ --ddc-item-object-fit: contain;
136
+ /* Defaults background color for the carousel */
137
+ --ddc-item-background-color: var(--dds-color-common-surface-secondary);
138
+ /* Defaults gap between carousel items */
139
+ --ddc-item-gap: var(--dds-space-100);
140
+ }
141
+
142
+ slot {
143
+ display: contents;
144
+ }
65
145
 
66
- --ddc-transition-duration: ${(0, lit.unsafeCSS)(DEFAULT_TRANSITION_DURATION)};
146
+ /* Ensure slides take up exactly 100% of the viewport container without subpixel overflow */
147
+ ::slotted(daikin-carousel-item) {
148
+ flex: 0 0 100% !important;
149
+ min-width: 0 !important;
150
+ max-width: 100% !important;
151
+ margin: 0 !important;
152
+ padding: 0 !important;
153
+ box-sizing: border-box !important;
67
154
  }
68
155
  `;
69
156
  }
157
+ _getEmblaDuration() {
158
+ const cssDurationMs = parseDurationMs(getComputedStyle(this).getPropertyValue("--ddc-transition-duration"));
159
+ if (cssDurationMs == null) return this.duration;
160
+ return cssDurationMs / LEGACY_CSS_DURATION_MS * DEFAULT_EMBLA_DURATION;
161
+ }
162
+ connectedCallback() {
163
+ super.connectedCallback();
164
+ this._mediaResizeObserver = new ResizeObserver((entries) => {
165
+ if (entries.length > 0) {
166
+ const height = entries[0].contentRect.height;
167
+ if (height > 0) this.style.setProperty("--ddc-arrow-y", `${height / 2}px`);
168
+ }
169
+ });
170
+ this.updateComplete.then(() => {
171
+ if (this.isConnected) this._handleSlotchange();
172
+ });
173
+ }
174
+ disconnectedCallback() {
175
+ super.disconnectedCallback();
176
+ this._mediaResizeObserver?.disconnect();
177
+ if (this._emblaApi) {
178
+ this._emblaApi.destroy();
179
+ this._emblaApi = void 0;
180
+ }
181
+ }
70
182
  _emitSelect(operation, beforeCurrentIndex) {
71
183
  this.dispatchEvent(new CustomEvent("select", { detail: {
72
184
  operation,
73
185
  beforeCurrentIndex
74
186
  } }));
75
187
  }
188
+ /**
189
+ * Initializes or re-initializes the Embla instance when properties or slots change.
190
+ */
191
+ _initEmbla() {
192
+ if (!this._viewport.value || !this._track.value) return;
193
+ const options = {
194
+ loop: this.loop,
195
+ align: "start",
196
+ containScroll: "trimSnaps",
197
+ slides: this._items,
198
+ container: this._track.value,
199
+ duration: this._getEmblaDuration(),
200
+ startIndex: this.currentIndex
201
+ };
202
+ if (this._emblaApi) this._emblaApi.reInit(options);
203
+ else {
204
+ this._emblaApi = (0, embla_carousel.default)(this._viewport.value, options);
205
+ this._emblaApi.on("select", this._onEmblaSelect);
206
+ this._emblaApi.on("pointerDown", this._onEmblaPointerDown);
207
+ this._emblaApi.on("settle", this._onEmblaSettle);
208
+ }
209
+ }
76
210
  _handleClickIndicator(index) {
77
- const beforeCurrentIndex = this.currentIndex;
78
- this.currentIndex = index;
79
- this._emitSelect("indicator", beforeCurrentIndex);
211
+ if (!this._emblaApi) return;
212
+ this._pendingOperation = "indicator";
213
+ this._emblaApi.scrollTo(index);
80
214
  }
81
215
  _handleKeydownIndicator(event) {
82
216
  const moveOffset = {
@@ -84,74 +218,160 @@ var DaikinCarousel = class DaikinCarousel extends require_dds_element.DDSElement
84
218
  ArrowLeft: -1
85
219
  }[event.key];
86
220
  if (!moveOffset) return;
221
+ event.preventDefault();
87
222
  const buttons = [...this._indicatorButtonsContainer.value?.querySelectorAll("button") ?? []];
223
+ const focusedIndex = buttons.indexOf(event.target);
224
+ if (focusedIndex < 0) return;
88
225
  this._moveBy(moveOffset);
89
- buttons[this.currentIndex].focus();
226
+ let targetIndex = focusedIndex + moveOffset;
227
+ if (this.loop) targetIndex = (targetIndex + this._itemCount) % this._itemCount;
228
+ else targetIndex = Math.max(0, Math.min(targetIndex, this._itemCount - 1));
229
+ buttons[targetIndex]?.focus();
90
230
  }
91
- _handleSlotchange() {
92
- const items = this._items;
93
- this._itemCount = items.length;
94
- for (const [index, item] of items.entries()) item.label = `${index + 1} of ${this._itemCount}`;
95
- this._updateItemActive();
231
+ _moveBy(offset) {
232
+ if (!this._emblaApi) return;
233
+ this._pendingOperation = offset === 1 ? "next" : "prev";
234
+ if (offset === 1) this._emblaApi.scrollNext();
235
+ else this._emblaApi.scrollPrev();
96
236
  }
97
- _moveBy(moveOffset) {
98
- const newIndex = this.currentIndex + moveOffset;
99
- if (newIndex < 0 || newIndex >= this._itemCount) return;
100
- const oldIndex = this.currentIndex;
101
- this.currentIndex = newIndex;
102
- this._emitSelect(moveOffset === 1 ? "next" : "prev", oldIndex);
237
+ async _handleSlotchange() {
238
+ await this.updateComplete;
239
+ this._itemCount = this._items.length;
240
+ for (const [index, item] of this._items.entries()) item.label = `${index + 1} of ${this._itemCount}`;
241
+ this._updateItemActive();
242
+ if (this._items.length > 0 && this._mediaResizeObserver) {
243
+ this._mediaResizeObserver.disconnect();
244
+ const mediaContainer = this._items[this.currentIndex].shadowRoot?.querySelector(".media-container");
245
+ if (mediaContainer) this._mediaResizeObserver.observe(mediaContainer);
246
+ }
247
+ requestAnimationFrame(() => {
248
+ if (this.isConnected) this._initEmbla();
249
+ });
103
250
  }
104
251
  _updateItemActive() {
105
252
  if (this._items.length - 1 < this.currentIndex) {
106
- console.warn(`Invalid 'current-index' property: ${this.currentIndex}. The number of actual 'daikin-carousel-item's exceeds the number of items.`);
107
- return;
253
+ console.warn(`Invalid 'current-index' property: ${this.currentIndex}. It exceeds the maximum item index. Correcting to ${Math.max(0, this._itemCount - 1)}.`);
254
+ this.currentIndex = Math.max(0, this._itemCount - 1);
108
255
  }
109
256
  if (this.currentIndex < 0) {
110
- console.warn(`Invalid 'current-item' property: ${this.currentIndex}. Negative values cannot be set.`);
111
- return;
257
+ console.warn(`Invalid 'current-index' property: ${this.currentIndex}. Negative values cannot be set. Correcting to 0.`);
258
+ this.currentIndex = 0;
112
259
  }
113
260
  for (const [index, item] of this._items.entries()) item.active = index === this.currentIndex;
114
261
  }
115
262
  render() {
116
- return lit.html`<div
117
- class="flex justify-center items-center flex-col gap-8"
118
- style=${`--total:${this._itemCount};--current:${this.currentIndex};`}
119
- >
120
- <div class="flex justify-center items-center w-full gap-4">
121
- <daikin-icon-button
122
- ${(0, lit_directives_ref_js.ref)(this._prevButton)}
123
- variant="ghost"
124
- color="neutral"
125
- button-aria-label="Previous"
126
- ?disabled=${this.currentIndex <= 0}
127
- @click=${() => this._moveBy(-1)}
263
+ return lit.html`<div class="flex justify-center items-center flex-col gap-8">
264
+ <!-- items-center is intentionally removed so the outside arrow wrappers can stretch to the full height. -->
265
+ <div class="flex w-full gap-4 relative">
266
+ <!-- Outside Prev Arrow -->
267
+ <div class=${outsideButtonWrapper({ arrows: this.arrows })}>
268
+ <!-- Absolutely center the arrow based on the computed media height. -->
269
+ <div
270
+ class="absolute w-full top-(--ddc-arrow-y,50%) -translate-y-1/2 flex justify-center"
271
+ >
272
+ <daikin-icon-button
273
+ variant="ghost"
274
+ color="neutral"
275
+ button-aria-label="Previous"
276
+ ?disabled=${this._itemCount <= 1 || !this.loop && this.currentIndex <= 0}
277
+ @click=${() => this._moveBy(-1)}
278
+ >
279
+ <span
280
+ class=${cvaButton({
281
+ intent: "previous",
282
+ arrows: "outside"
283
+ })}
284
+ ></span>
285
+ </daikin-icon-button>
286
+ </div>
287
+ </div>
288
+
289
+ <!-- Inside Prev Arrow -->
290
+ <div
291
+ class=${insideButtonWrapper({
292
+ arrows: this.arrows,
293
+ intent: "previous"
294
+ })}
128
295
  >
129
- <span class=${cvaButton({ intent: "previous" })}></span>
130
- </daikin-icon-button>
296
+ <daikin-icon-button
297
+ class=${INJECTION_CLASS_INSIDE_BUTTON}
298
+ variant="ghost"
299
+ color="neutral"
300
+ size="m"
301
+ button-aria-label="Previous"
302
+ ?disabled=${this._itemCount <= 1 || !this.loop && this.currentIndex <= 0}
303
+ @click=${() => this._moveBy(-1)}
304
+ >
305
+ <span
306
+ class=${cvaButton({
307
+ intent: "previous",
308
+ arrows: "inside"
309
+ })}
310
+ ></span>
311
+ </daikin-icon-button>
312
+ </div>
313
+
314
+ <!-- Viewport -->
131
315
  <div
132
- class="w-full overflow-clip relative focus-within:outline-solid focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ddt-color-common-border-focus @container"
316
+ ${(0, lit_directives_ref_js.ref)(this._viewport)}
317
+ data-carousel-viewport
318
+ class="flex-1 min-w-0 overflow-hidden focus-within:outline-solid focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ddt-color-common-border-focus"
133
319
  aria-live="polite"
134
320
  >
321
+ <div ${(0, lit_directives_ref_js.ref)(this._track)} class="flex touch-pan-y">
322
+ <slot @slotchange=${this._handleSlotchange}></slot>
323
+ </div>
324
+ </div>
325
+
326
+ <!-- Inside Next Arrow -->
327
+ <div
328
+ class=${insideButtonWrapper({
329
+ arrows: this.arrows,
330
+ intent: "next"
331
+ })}
332
+ >
333
+ <daikin-icon-button
334
+ class=${INJECTION_CLASS_INSIDE_BUTTON}
335
+ variant="ghost"
336
+ color="neutral"
337
+ size="m"
338
+ button-aria-label="Next"
339
+ ?disabled=${this._itemCount <= 1 || !this.loop && this.currentIndex >= this._itemCount - 1}
340
+ @click=${() => this._moveBy(1)}
341
+ >
342
+ <span
343
+ class=${cvaButton({
344
+ intent: "next",
345
+ arrows: "inside"
346
+ })}
347
+ ></span>
348
+ </daikin-icon-button>
349
+ </div>
350
+
351
+ <!-- Outside Next Arrow -->
352
+ <div class=${outsideButtonWrapper({ arrows: this.arrows })}>
135
353
  <div
136
- class="flex w-[calc(100cqw*var(--total))] transition-transform translate-x-[calc(-100%*var(--current)/var(--total))] duration-(--ddc-transition-duration)"
354
+ class="absolute w-full top-(--ddc-arrow-y,50%) -translate-y-1/2 flex justify-center"
137
355
  >
138
- <slot
139
- class="slotted:w-[calc(100%/var(--total))]"
140
- @slotchange=${this._handleSlotchange}
141
- ></slot>
356
+ <daikin-icon-button
357
+ variant="ghost"
358
+ color="neutral"
359
+ button-aria-label="Next"
360
+ ?disabled=${this._itemCount <= 1 || !this.loop && this.currentIndex >= this._itemCount - 1}
361
+ @click=${() => this._moveBy(1)}
362
+ >
363
+ <span
364
+ class=${cvaButton({
365
+ intent: "next",
366
+ arrows: "outside"
367
+ })}
368
+ ></span>
369
+ </daikin-icon-button>
142
370
  </div>
143
371
  </div>
144
- <daikin-icon-button
145
- ${(0, lit_directives_ref_js.ref)(this._nextButton)}
146
- variant="ghost"
147
- color="neutral"
148
- button-aria-label="Next"
149
- ?disabled=${this.currentIndex >= this._itemCount - 1}
150
- @click=${() => this._moveBy(1)}
151
- >
152
- <span class=${cvaButton({ intent: "next" })}></span>
153
- </daikin-icon-button>
154
372
  </div>
373
+
374
+ <!-- Indicators remain unchanged. -->
155
375
  <div class="flex gap-3">
156
376
  <div
157
377
  ${(0, lit_directives_ref_js.ref)(this._indicatorButtonsContainer)}
@@ -159,7 +379,7 @@ var DaikinCarousel = class DaikinCarousel extends require_dds_element.DDSElement
159
379
  role="tablist"
160
380
  @keydown=${this._handleKeydownIndicator}
161
381
  >
162
- ${(0, lit_directives_repeat_js.repeat)(this._items, (_, index) => index, (_, index) => lit.html`<button
382
+ ${(0, lit_directives_repeat_js.repeat)([...Array(this._itemCount).keys()], (index) => index, (index) => lit.html`<button
163
383
  type="button"
164
384
  class=${INDICATOR_CLASS_NAME}
165
385
  aria-label="Slide ${index + 1}"
@@ -173,7 +393,11 @@ var DaikinCarousel = class DaikinCarousel extends require_dds_element.DDSElement
173
393
  </div>`;
174
394
  }
175
395
  updated(changedProperties) {
176
- if (changedProperties.has("currentIndex")) this._updateItemActive();
396
+ if (changedProperties.has("currentIndex")) {
397
+ if (this._emblaApi && this._emblaApi.selectedScrollSnap() !== this.currentIndex) this._emblaApi.scrollTo(this.currentIndex);
398
+ this._updateItemActive();
399
+ }
400
+ if (changedProperties.has("loop") || changedProperties.has("duration")) this._initEmbla();
177
401
  }
178
402
  };
179
403
  require_decorate.default([require_dds_property.property({
@@ -181,6 +405,23 @@ require_decorate.default([require_dds_property.property({
181
405
  reflect: true,
182
406
  attribute: "current-index"
183
407
  })], DaikinCarousel.prototype, "currentIndex", void 0);
408
+ require_decorate.default([require_dds_property.property({
409
+ type: Boolean,
410
+ attribute: "loop"
411
+ })], DaikinCarousel.prototype, "loop", void 0);
412
+ require_decorate.default([require_dds_property.property({
413
+ type: String,
414
+ reflect: true,
415
+ fallbackValue: "outside",
416
+ isAllowedValue: require_dds_property.oneOf(["outside", "inside"])
417
+ })], DaikinCarousel.prototype, "arrows", void 0);
418
+ require_decorate.default([require_dds_property.property({
419
+ type: Number,
420
+ reflect: true,
421
+ attribute: "duration",
422
+ fallbackValue: DEFAULT_EMBLA_DURATION,
423
+ isAllowedValue: (value) => typeof value === "number" && Number.isFinite(value) && value >= 0
424
+ })], DaikinCarousel.prototype, "duration", void 0);
184
425
  require_decorate.default([(0, lit_decorators_js.queryAssignedElements)({ selector: "daikin-carousel-item" })], DaikinCarousel.prototype, "_items", void 0);
185
426
  require_decorate.default([(0, lit_decorators_js.state)()], DaikinCarousel.prototype, "_itemCount", void 0);
186
427
  DaikinCarousel = require_decorate.default([require_decorators.ddsElement("daikin-carousel")], DaikinCarousel);
@@ -3,16 +3,20 @@ import { DDSElement } from "../../base/index.cjs";
3
3
  /**
4
4
  * A carousel is a component that displays multiple pieces of information by sliding left and right within a fixed height area.
5
5
  *
6
- * The carousel component can be operated in several ways (Control, Indicator, and Swipe), but it is not possible to hide all of these, as this would prevent the user from being able to operate the carousel component.
6
+ * Powered by embla-carousel for smooth, native-feeling interactions and infinite loops.
7
7
  *
8
8
  * Hierarchy:
9
9
  * - `daikin-carousel` > `daikin-carousel-item`
10
10
  *
11
- * @fires select - If an item in the carousel is selected in some way, the method used to select it, the index number of the item displayed before it, and the index number of the item currently displayed are passed.
11
+ * @fires select - Fired when the carousel index changes. `event.detail` contains the triggering `operation` (`"prev"`, `"next"`, `"indicator"`, or `"swipe"`) and `beforeCurrentIndex`; read `currentIndex` for the selected index.
12
12
  *
13
13
  * @slot - A slot for carousel items. Place `daikin-carousel-item` elements here.
14
14
  *
15
- * @cssprop [--ddc-transition-duration=600ms] - Specify the interval for the slide animation.
15
+ * @cssprop [--ddc-transition-duration=600ms] - Legacy transition duration in milliseconds. **Warning:** Mapped to Embla's duration option using 600ms = 25. This property may be removed in a future release; gradually migrate to the `duration` property instead.
16
+ * @cssprop [--ddc-item-aspect-ratio=16/9] - The aspect ratio of every carousel item's media container.
17
+ * @cssprop [--ddc-item-object-fit=contain] - How image/video content fits inside every carousel item's media container.
18
+ * @cssprop [--ddc-item-background-color=var(--dds-color-common-surface-secondary)] - The default background color for the carousel items.
19
+ * @cssprop [--ddc-item-gap=var(--dds-space-100)] - The gap between carousel items.
16
20
  *
17
21
  * @example
18
22
  *
@@ -33,19 +37,58 @@ export declare class DaikinCarousel extends DDSElement {
33
37
  static readonly styles: import('lit').CSSResult;
34
38
  /**
35
39
  * The index number of the content currently being displayed.
36
- * When controlling this property externally, listen to the `select` event and read the updated `currentIndex` from the component to keep your state in sync.
37
40
  */
38
41
  currentIndex: number;
42
+ /**
43
+ * Whether the carousel should loop back to the first item when the last item is reached.
44
+ */
45
+ loop: boolean;
46
+ /**
47
+ * The position of the navigation arrows. Can be either "outside" or "inside".
48
+ * - "outside": Arrows are placed outside the carousel viewport.
49
+ * - "inside": Arrows are placed inside the carousel viewport.
50
+ * The inside option is useful for carousels with a smaller width, where the arrows can be placed over the content without taking up additional space.
51
+ * When the width of viewport is smaller than mobile breakpoint (768px), the arrows will always be placed inside regardless of this property.
52
+ *
53
+ * @default "outside"
54
+ */
55
+ arrows: "outside" | "inside";
56
+ /**
57
+ * The higher this value, the slower the image scrolling animation. However, this value does not affect the sliding speed when the user is dragging the image, as that depends on the user's dragging speed.
58
+ *
59
+ * @default 25
60
+ */
61
+ duration: number;
39
62
  private readonly _items;
63
+ /**
64
+ * Keeps track of the total number of slotted carousel items.
65
+ */
40
66
  private _itemCount;
41
- private _prevButton;
42
- private _nextButton;
67
+ private _emblaApi?;
68
+ private _mediaResizeObserver?;
43
69
  private _indicatorButtonsContainer;
70
+ private _viewport;
71
+ private _track;
72
+ private _pendingOperation;
73
+ private _isDragging;
74
+ private _getEmblaDuration;
75
+ connectedCallback(): void;
76
+ disconnectedCallback(): void;
44
77
  private _emitSelect;
78
+ /**
79
+ * Initializes or re-initializes the Embla instance when properties or slots change.
80
+ */
81
+ private _initEmbla;
82
+ private _onEmblaPointerDown;
83
+ private _onEmblaSettle;
84
+ /**
85
+ * Embla event listener that synchronizes internal state when the user swipes or slides.
86
+ */
87
+ private _onEmblaSelect;
45
88
  private _handleClickIndicator;
46
89
  private _handleKeydownIndicator;
47
- private _handleSlotchange;
48
90
  private _moveBy;
91
+ private _handleSlotchange;
49
92
  private _updateItemActive;
50
93
  render(): import('lit-html').TemplateResult<1>;
51
94
  protected updated(changedProperties: PropertyValues): void;
@@ -22,6 +22,17 @@ var DaikinCarouselItem = class DaikinCarouselItem extends require_dds_element.DD
22
22
  display: block;
23
23
  width: 100%;
24
24
  }
25
+
26
+ .media-container {
27
+ aspect-ratio: var(--ddc-item-aspect-ratio);
28
+ }
29
+
30
+ ::slotted(img),
31
+ ::slotted(video) {
32
+ width: 100% !important;
33
+ height: 100% !important;
34
+ object-fit: var(--ddc-item-object-fit);
35
+ }
25
36
  `;
26
37
  }
27
38
  _handleFooterSlotChange() {
@@ -29,12 +40,17 @@ var DaikinCarouselItem = class DaikinCarouselItem extends require_dds_element.DD
29
40
  }
30
41
  render() {
31
42
  return lit.html`<div
32
- class="flex flex-col flex-none gap-3 text-ddt-color-common-text-primary overflow-hidden"
43
+ class="flex flex-col flex-none gap-3 text-ddt-color-common-text-primary overflow-hidden px-[calc(var(--ddc-item-gap)/2)]"
33
44
  role="tabpanel"
34
45
  aria-label=${this.label}
35
46
  aria-hidden=${!this.active}
36
47
  >
37
- <slot></slot>
48
+ <div
49
+ class="media-container flex w-full flex-none items-center justify-center overflow-hidden bg-(--ddc-item-background-color)"
50
+ >
51
+ <slot></slot>
52
+ </div>
53
+
38
54
  <div
39
55
  class="visible:flex flex-col gap-2"
40
56
  ?hidden=${!this._hasTextContents}
@@ -22,11 +22,7 @@ import { DDSElement } from "../../base/index.cjs";
22
22
  export declare class DaikinCarouselItem extends DDSElement {
23
23
  static readonly styles: import('lit').CSSResult;
24
24
  /**
25
- * _Internal use._
26
- * Item's aria label.
27
- * Controlled by `daikin-carousel`.
28
- *
29
- * @private
25
+ * The Aria label for the carousel item.
30
26
  */
31
27
  label: string;
32
28
  /**