@dryui/ui 0.1.2 → 0.1.4

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 (79) hide show
  1. package/dist/accordion/accordion-trigger.svelte +5 -6
  2. package/dist/alert-dialog/alert-dialog-action.svelte +42 -6
  3. package/dist/alert-dialog/alert-dialog-cancel.svelte +44 -5
  4. package/dist/alert-dialog/alert-dialog-footer.svelte +3 -2
  5. package/dist/aurora/aurora.svelte.d.ts +6 -0
  6. package/dist/beam/beam.svelte +17 -10
  7. package/dist/button/button.svelte +51 -1
  8. package/dist/button-group/button-group.svelte +7 -62
  9. package/dist/button-group/context.svelte.d.ts +5 -0
  10. package/dist/button-group/context.svelte.js +11 -0
  11. package/dist/chromatic-aberration/chromatic-aberration.svelte +60 -18
  12. package/dist/collapsible/collapsible-trigger.svelte +4 -7
  13. package/dist/color-picker/color-picker-eyedropper.svelte +4 -11
  14. package/dist/combobox/combobox-group.svelte +1 -1
  15. package/dist/data-grid/data-grid-pagination.svelte +20 -2
  16. package/dist/data-grid/data-grid-root.svelte +1 -0
  17. package/dist/date-field/date-field-root.svelte +66 -20
  18. package/dist/date-field/date-field-segment.svelte +11 -9
  19. package/dist/date-field/date-field-separator.svelte +9 -1
  20. package/dist/date-picker/datepicker-calendar.svelte +168 -13
  21. package/dist/date-picker/datepicker-trigger.svelte +3 -8
  22. package/dist/date-range-picker/date-range-picker-calendar.svelte +177 -13
  23. package/dist/date-range-picker/date-range-picker-root.svelte +0 -6
  24. package/dist/date-range-picker/date-range-picker-trigger.svelte +18 -12
  25. package/dist/dialog/dialog-content.svelte +1 -0
  26. package/dist/field/field-root.svelte +0 -1
  27. package/dist/file-select/file-select-clear.svelte +2 -8
  28. package/dist/file-upload/file-upload-item-delete.svelte +4 -7
  29. package/dist/file-upload/file-upload-root.svelte +0 -4
  30. package/dist/flip-card/flip-card-back.svelte +2 -2
  31. package/dist/flip-card/flip-card-front.svelte +2 -2
  32. package/dist/flip-card/flip-card-root.svelte +2 -0
  33. package/dist/float-button/float-button-root.svelte +2 -1
  34. package/dist/image-comparison/image-comparison.svelte +16 -24
  35. package/dist/input-group/input-group-action.svelte +5 -0
  36. package/dist/input-group/input-group-input.svelte +7 -2
  37. package/dist/input-group/input-group-prefix.svelte +5 -0
  38. package/dist/input-group/input-group-root.svelte +10 -2
  39. package/dist/input-group/input-group-select.svelte +5 -0
  40. package/dist/input-group/input-group-separator.svelte +10 -0
  41. package/dist/input-group/input-group-suffix.svelte +5 -0
  42. package/dist/list/list-item-icon.svelte +8 -0
  43. package/dist/list/list-item-text.svelte +19 -0
  44. package/dist/list/list-item.svelte +42 -0
  45. package/dist/list/list-root.svelte +0 -71
  46. package/dist/list/list-subheader.svelte +11 -0
  47. package/dist/map/map-marker.svelte +10 -0
  48. package/dist/map/map-popup.svelte +7 -0
  49. package/dist/map/map-root.svelte +0 -30
  50. package/dist/multi-select-combobox/multi-select-combobox-group.svelte +1 -1
  51. package/dist/option-swatch-group/option-swatch-group-item.svelte +46 -0
  52. package/dist/option-swatch-group/option-swatch-group-label.svelte +10 -0
  53. package/dist/option-swatch-group/option-swatch-group-meta.svelte +10 -0
  54. package/dist/option-swatch-group/option-swatch-group-root.svelte +0 -79
  55. package/dist/option-swatch-group/option-swatch-group-swatch.svelte +25 -6
  56. package/dist/pin-input/pin-input-cell.svelte +4 -1
  57. package/dist/radio-group/radio-group-item.svelte +90 -0
  58. package/dist/radio-group/radio-group.svelte +0 -89
  59. package/dist/range-calendar/range-calendar-grid.svelte +217 -179
  60. package/dist/range-calendar/range-calendar-root.svelte +24 -10
  61. package/dist/rich-text-editor/rich-text-editor-content.svelte +91 -3
  62. package/dist/rich-text-editor/rich-text-editor-root.svelte +168 -3
  63. package/dist/rich-text-editor/rich-text-editor-toolbar.svelte +318 -275
  64. package/dist/select/select-trigger.svelte +5 -8
  65. package/dist/shader-canvas/shader-canvas.svelte +0 -3
  66. package/dist/sidebar/sidebar-trigger.svelte +3 -2
  67. package/dist/system-map/system-map.svelte +120 -674
  68. package/dist/tabs/tabs-trigger.svelte +7 -4
  69. package/dist/tags-input/tags-input-input.svelte +3 -0
  70. package/dist/tags-input/tags-input-root.svelte +4 -13
  71. package/dist/tags-input/tags-input-tag.svelte +3 -0
  72. package/dist/themes/dark.css +6 -0
  73. package/dist/themes/default.css +3 -0
  74. package/dist/toast/toast-action.svelte +1 -0
  75. package/dist/toast/toast-close.svelte +4 -0
  76. package/dist/toast/toast-provider.svelte +5 -26
  77. package/dist/toast/toast-root.svelte +5 -10
  78. package/dist/virtual-list/virtual-list.svelte +187 -3
  79. package/package.json +3 -3
@@ -24,6 +24,16 @@
24
24
 
25
25
  let containerEl = $state<HTMLDivElement>();
26
26
 
27
+ function bindContainer(node: HTMLDivElement) {
28
+ containerEl = node;
29
+
30
+ return () => {
31
+ if (containerEl === node) {
32
+ containerEl = undefined;
33
+ }
34
+ };
35
+ }
36
+
27
37
  const weekdayLabels = $derived(generateWeekdayLabels(ctx.locale, ctx.weekStartDay));
28
38
 
29
39
  const calendarDays = $derived(getCalendarDays(ctx.viewYear, ctx.viewMonth, ctx.weekStartDay));
@@ -116,35 +126,47 @@
116
126
  }
117
127
  </script>
118
128
 
119
- <div bind:this={containerEl} class={className} {...rest} data-drp-calendar>
129
+ <div {@attach bindContainer} class={className} {...rest} data-drp-calendar>
120
130
  <!-- Calendar header: month/year + navigation -->
121
- <div role="group" aria-label={monthYearLabel}>
122
- <div>
123
- <button type="button" aria-label="Previous month" onclick={() => ctx.prevMonth()}>
131
+ <div role="group" aria-label={monthYearLabel} data-calendar-panel>
132
+ <div data-calendar-header>
133
+ <button
134
+ type="button"
135
+ aria-label="Previous month"
136
+ data-calendar-nav
137
+ disabled={ctx.disabled}
138
+ onclick={() => ctx.prevMonth()}
139
+ >
124
140
  &#8249;
125
141
  </button>
126
- <span aria-live="polite" aria-atomic="true">
142
+ <span aria-live="polite" aria-atomic="true" data-calendar-heading>
127
143
  {monthYearLabel}
128
144
  </span>
129
- <button type="button" aria-label="Next month" onclick={() => ctx.nextMonth()}>
145
+ <button
146
+ type="button"
147
+ aria-label="Next month"
148
+ data-calendar-nav
149
+ disabled={ctx.disabled}
150
+ onclick={() => ctx.nextMonth()}
151
+ >
130
152
  &#8250;
131
153
  </button>
132
154
  </div>
133
155
 
134
156
  <!-- Day-of-week header row -->
135
157
  <div role="grid" aria-label={monthYearLabel}>
136
- <div role="row">
137
- {#each weekdayLabels as label}
138
- <div role="columnheader" aria-label={label}>
158
+ <div role="row" data-calendar-row>
159
+ {#each weekdayLabels as label (label)}
160
+ <div role="columnheader" aria-label={label} data-calendar-columnheader>
139
161
  <span aria-hidden="true">{label}</span>
140
162
  </div>
141
163
  {/each}
142
164
  </div>
143
165
 
144
166
  <!-- Calendar day grid -->
145
- {#each weeks as week}
146
- <div role="row">
147
- {#each week as day}
167
+ {#each weeks as week, weekIndex (weekIndex)}
168
+ <div role="row" data-calendar-row>
169
+ {#each week as day (getDayISOString(day))}
148
170
  {@const isCurrent = day.getMonth() === ctx.viewMonth}
149
171
  {@const selected = isSelected(day)}
150
172
  {@const today = isToday(day)}
@@ -154,7 +176,7 @@
154
176
  {@const inRange = isInSelectedRange(day) || isInPreviewRange(day)}
155
177
  {@const rangeStart = isRangeStart(day)}
156
178
  {@const rangeEnd = isRangeEnd(day)}
157
- <div role="gridcell">
179
+ <div role="gridcell" data-calendar-cell>
158
180
  <button
159
181
  type="button"
160
182
  tabindex={focused ? 0 : -1}
@@ -165,6 +187,7 @@
165
187
  })}
166
188
  aria-pressed={selected}
167
189
  aria-disabled={disabled}
190
+ data-calendar-day-button
168
191
  data-calendar-day={isoStr}
169
192
  data-today={today ? '' : undefined}
170
193
  data-selected={selected ? '' : undefined}
@@ -200,5 +223,146 @@
200
223
  [data-drp-calendar] {
201
224
  display: grid;
202
225
  gap: var(--dry-space-2);
226
+ user-select: none;
227
+ color: var(--dry-color-text-strong);
228
+ font-family: var(--dry-font-sans);
229
+ }
230
+
231
+ [data-drp-calendar] [data-calendar-panel] {
232
+ display: grid;
233
+ gap: var(--dry-space-2);
234
+ }
235
+
236
+ [data-drp-calendar] [data-calendar-header] {
237
+ display: grid;
238
+ grid-template-columns: auto 1fr auto;
239
+ align-items: center;
240
+ gap: var(--dry-space-2);
241
+ }
242
+
243
+ [data-drp-calendar] [data-calendar-nav] {
244
+ display: inline-grid;
245
+ place-items: center;
246
+ height: var(--dry-space-8);
247
+ aspect-ratio: 1;
248
+ border: 1px solid transparent;
249
+ border-radius: var(--dry-range-calendar-day-radius, var(--dry-radius-md));
250
+ background: transparent;
251
+ color: var(--dry-color-text-strong);
252
+ cursor: pointer;
253
+ transition:
254
+ background var(--dry-duration-fast) var(--dry-ease-default),
255
+ border-color var(--dry-duration-fast) var(--dry-ease-default);
256
+ }
257
+
258
+ [data-drp-calendar] [data-calendar-nav]:hover:not([disabled]) {
259
+ background: var(--dry-range-calendar-day-hover-bg, var(--dry-color-bg-raised));
260
+ border-color: var(--dry-color-stroke-strong);
261
+ }
262
+
263
+ [data-drp-calendar] [data-calendar-nav]:focus-visible {
264
+ outline: 2px solid var(--dry-color-focus-ring);
265
+ outline-offset: 1px;
266
+ }
267
+
268
+ [data-drp-calendar] [data-calendar-heading] {
269
+ font-size: var(--dry-type-small-size, var(--dry-type-small-size));
270
+ font-weight: 600;
271
+ letter-spacing: -0.01em;
272
+ }
273
+
274
+ [data-drp-calendar] [role='grid'] {
275
+ display: grid;
276
+ gap: 1px;
277
+ }
278
+
279
+ [data-drp-calendar] [data-calendar-row] {
280
+ display: grid;
281
+ grid-template-columns: repeat(7, minmax(0, 1fr));
282
+ gap: 1px;
283
+ }
284
+
285
+ [data-drp-calendar] [data-calendar-columnheader] {
286
+ display: grid;
287
+ place-items: center;
288
+ min-height: var(--dry-space-8);
289
+ font-size: var(--dry-type-tiny-size, var(--dry-type-tiny-size));
290
+ color: var(--dry-range-calendar-outside-color, var(--dry-color-text-weak));
291
+ text-transform: uppercase;
292
+ letter-spacing: 0.04em;
293
+ }
294
+
295
+ [data-drp-calendar] [data-calendar-cell] {
296
+ display: grid;
297
+ place-items: center;
298
+ }
299
+
300
+ [data-drp-calendar] [data-calendar-day-button] {
301
+ display: inline-grid;
302
+ place-items: center;
303
+ min-height: var(--dry-range-calendar-day-size, 2.25rem);
304
+ aspect-ratio: 1;
305
+ border: none;
306
+ border-radius: var(--dry-range-calendar-day-radius, var(--dry-radius-md));
307
+ background: transparent;
308
+ color: var(--dry-color-text-strong);
309
+ font: inherit;
310
+ font-size: var(--dry-type-small-size, var(--dry-type-small-size));
311
+ font-variant-numeric: tabular-nums;
312
+ cursor: pointer;
313
+ transition:
314
+ background var(--dry-duration-fast) var(--dry-ease-default),
315
+ color var(--dry-duration-fast) var(--dry-ease-default);
316
+ }
317
+
318
+ [data-drp-calendar] [data-calendar-day-button]:hover:not([data-disabled]) {
319
+ background: var(--dry-range-calendar-day-hover-bg, var(--dry-color-bg-raised));
320
+ }
321
+
322
+ [data-drp-calendar] [data-calendar-day-button]:focus-visible {
323
+ outline: 2px solid var(--dry-color-focus-ring);
324
+ outline-offset: 1px;
325
+ }
326
+
327
+ [data-drp-calendar]
328
+ [data-calendar-day-button][data-today]:not([data-range-start]):not([data-range-end]) {
329
+ color: var(--dry-range-calendar-today-color, var(--dry-color-fill-brand));
330
+ font-weight: 600;
331
+ }
332
+
333
+ [data-drp-calendar] [data-calendar-day-button][data-range-start],
334
+ [data-drp-calendar] [data-calendar-day-button][data-range-end] {
335
+ background: var(--dry-range-calendar-selected-bg, var(--dry-color-fill-brand));
336
+ color: var(--dry-range-calendar-selected-color, var(--dry-color-on-brand));
337
+ font-weight: 600;
338
+ }
339
+
340
+ [data-drp-calendar] [data-calendar-day-button][data-range-start]:hover:not([data-disabled]),
341
+ [data-drp-calendar] [data-calendar-day-button][data-range-end]:hover:not([data-disabled]) {
342
+ background: var(--dry-range-calendar-selected-hover-bg, var(--dry-color-fill-brand-hover));
343
+ }
344
+
345
+ [data-drp-calendar] [data-calendar-day-button][data-in-range] {
346
+ background: var(
347
+ --dry-range-calendar-range-bg,
348
+ color-mix(in srgb, var(--dry-color-fill-brand) 15%, transparent)
349
+ );
350
+ border-radius: 0;
351
+ }
352
+
353
+ [data-drp-calendar] [data-calendar-day-button][data-range-start],
354
+ [data-drp-calendar] [data-calendar-day-button][data-range-end] {
355
+ border-radius: var(--dry-range-calendar-day-radius, var(--dry-radius-md));
356
+ }
357
+
358
+ [data-drp-calendar] [data-calendar-day-button][data-outside-month] {
359
+ color: var(--dry-range-calendar-outside-color, var(--dry-color-text-weak));
360
+ opacity: 0.6;
361
+ }
362
+
363
+ [data-drp-calendar] [data-calendar-day-button][data-disabled] {
364
+ cursor: not-allowed;
365
+ opacity: 0.4;
366
+ pointer-events: none;
203
367
  }
204
368
  </style>
@@ -150,9 +150,3 @@
150
150
  </script>
151
151
 
152
152
  {@render children()}
153
-
154
- <style>
155
- [data-drp-root] {
156
- display: contents;
157
- }
158
- </style>
@@ -15,10 +15,19 @@
15
15
 
16
16
  let buttonEl = $state<HTMLButtonElement>();
17
17
 
18
- $effect(() => {
19
- if (!buttonEl) return;
20
- ctx.triggerEl = buttonEl;
21
- });
18
+ function bindTrigger(node: HTMLButtonElement) {
19
+ buttonEl = node;
20
+ ctx.triggerEl = node;
21
+
22
+ return () => {
23
+ if (buttonEl === node) {
24
+ buttonEl = undefined;
25
+ }
26
+ if (ctx.triggerEl === node) {
27
+ ctx.triggerEl = null;
28
+ }
29
+ };
30
+ }
22
31
 
23
32
  const formatOpts: Intl.DateTimeFormatOptions = {
24
33
  year: 'numeric',
@@ -38,7 +47,7 @@
38
47
  </script>
39
48
 
40
49
  <button
41
- bind:this={buttonEl}
50
+ {@attach bindTrigger}
42
51
  id={ctx.triggerId}
43
52
  type="button"
44
53
  aria-haspopup="dialog"
@@ -46,6 +55,7 @@
46
55
  aria-controls={ctx.contentId}
47
56
  data-state={ctx.open ? 'open' : 'closed'}
48
57
  data-disabled={ctx.disabled ? '' : undefined}
58
+ data-drp-trigger
49
59
  disabled={ctx.disabled}
50
60
  popovertarget={ctx.contentId}
51
61
  class={className}
@@ -58,6 +68,7 @@
58
68
  {displayText || placeholder}
59
69
  </span>
60
70
  {/if}
71
+ <svg data-indicator xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="3" y="4" width="18" height="17" rx="2" ry="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>
61
72
  </button>
62
73
 
63
74
  <style>
@@ -83,14 +94,9 @@
83
94
  box-shadow var(--dry-duration-fast) var(--dry-ease-default);
84
95
  }
85
96
 
86
- [data-drp-trigger]::after {
87
- content: '';
88
- aspect-ratio: 1;
97
+ [data-drp-trigger] [data-indicator] {
89
98
  height: 1rem;
90
- background: currentColor;
91
- mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Crect x='3' y='4' width='18' height='17' rx='2' ry='2'/%3E%3Cpath d='M16 2v4M8 2v4M3 10h18'/%3E%3C/svg%3E");
92
- mask-size: contain;
93
- mask-repeat: no-repeat;
99
+ aspect-ratio: 1;
94
100
  opacity: 0.75;
95
101
  }
96
102
 
@@ -82,6 +82,7 @@
82
82
  );
83
83
 
84
84
  container-type: inline-size;
85
+ justify-self: stretch;
85
86
  border: 1px solid var(--dry-dialog-border);
86
87
  border-radius: var(--dry-dialog-radius, var(--dry-overlay-radius, var(--dry-radius-2xl)));
87
88
  background: var(--dry-dialog-bg, var(--dry-overlay-bg, var(--dry-color-bg-overlay)));
@@ -76,7 +76,6 @@
76
76
  <style>
77
77
  [data-field] {
78
78
  --dry-field-gap: var(--dry-space-1_5);
79
- --dry-field-label-order: 1;
80
79
  display: grid;
81
80
  gap: var(--dry-field-gap);
82
81
 
@@ -25,7 +25,7 @@
25
25
  {#if children}
26
26
  {@render children()}
27
27
  {:else}
28
-
28
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
29
29
  {/if}
30
30
  </button>
31
31
  {/if}
@@ -47,15 +47,9 @@
47
47
  background var(--dry-duration-fast) var(--dry-ease-default);
48
48
  }
49
49
 
50
- [data-fs-clear]::before {
51
- content: '';
52
- display: block;
50
+ [data-fs-clear] svg {
53
51
  height: 0.875rem;
54
52
  aspect-ratio: 1;
55
- background: currentColor;
56
- mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M18 6 6 18'/%3E%3Cpath d='m6 6 12 12'/%3E%3C/svg%3E");
57
- mask-size: contain;
58
- mask-repeat: no-repeat;
59
53
  }
60
54
 
61
55
  [data-fs-clear]:hover {
@@ -23,6 +23,7 @@
23
23
  type="button"
24
24
  disabled={ctx.disabled}
25
25
  data-disabled={ctx.disabled || undefined}
26
+ data-fu-item-delete
26
27
  aria-label="Remove file"
27
28
  onclick={handleClick}
28
29
  {...rest}
@@ -30,6 +31,8 @@
30
31
  >
31
32
  {#if children}
32
33
  {@render children()}
34
+ {:else}
35
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
33
36
  {/if}
34
37
  </button>
35
38
 
@@ -50,15 +53,9 @@
50
53
  background var(--dry-duration-fast) var(--dry-ease-default);
51
54
  }
52
55
 
53
- [data-fu-item-delete]::before {
54
- content: '';
55
- display: block;
56
+ [data-fu-item-delete] svg {
56
57
  height: 1rem;
57
58
  aspect-ratio: 1;
58
- background: currentColor;
59
- mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M18 6 6 18'/%3E%3Cpath d='m6 6 12 12'/%3E%3C/svg%3E");
60
- mask-size: contain;
61
- mask-repeat: no-repeat;
62
59
  }
63
60
 
64
61
  [data-fu-item-delete]:hover:not([data-disabled]) {
@@ -142,8 +142,4 @@
142
142
  overflow: hidden;
143
143
  }
144
144
 
145
- [data-file-upload] {
146
- container-type: inline-size;
147
- display: grid;
148
- }
149
145
  </style>
@@ -27,8 +27,8 @@
27
27
  z-index: 1;
28
28
  backface-visibility: hidden;
29
29
  transition: transform var(--dry-flip-card-duration, 0.6s) ease;
30
- position: absolute;
31
- inset: 0;
30
+ grid-area: 1 / 1;
32
31
  transform: var(--dry-flip-card-back-transform, rotateY(180deg));
32
+ transform-origin: center;
33
33
  }
34
34
  </style>
@@ -18,8 +18,8 @@
18
18
  z-index: 2;
19
19
  backface-visibility: hidden;
20
20
  transition: transform var(--dry-flip-card-duration, 0.6s) ease;
21
- position: absolute;
22
- inset: 0;
21
+ grid-area: 1 / 1;
23
22
  transform: var(--dry-flip-card-front-transform, rotateY(0deg));
23
+ transform-origin: center;
24
24
  }
25
25
  </style>
@@ -66,8 +66,10 @@
66
66
  --dry-flip-card-front-transform: rotateY(0deg);
67
67
  --dry-flip-card-back-transform: rotateY(180deg);
68
68
 
69
+ display: grid;
69
70
  perspective: var(--dry-flip-card-perspective);
70
71
  position: relative;
72
+ transform-style: preserve-3d;
71
73
  }
72
74
 
73
75
  [data-flip-card][data-direction='horizontal'][data-flipped] {
@@ -35,9 +35,10 @@
35
35
  [data-float-button] {
36
36
  --dry-fab-offset: var(--dry-space-6);
37
37
  --dry-fab-gap: var(--dry-space-3);
38
+ --dry-fab-position: fixed;
38
39
  --dry-fab-z-index: var(--dry-layer-overlay);
39
40
 
40
- position: fixed;
41
+ position: var(--dry-fab-position);
41
42
  z-index: var(--dry-fab-z-index);
42
43
  display: grid;
43
44
  justify-items: center;
@@ -21,20 +21,15 @@
21
21
  ...rest
22
22
  }: Props = $props();
23
23
 
24
- let containerEl = $state<HTMLDivElement>();
25
24
  let dragging = $state(false);
26
25
 
27
- function setContainer(node: HTMLDivElement) {
28
- containerEl = node;
29
- return {
30
- destroy() {
31
- if (containerEl === node) containerEl = undefined;
32
- }
33
- };
26
+ function syncStyles(node: HTMLElement) {
27
+ $effect(() => {
28
+ node.style.cssText = `${style ? `${style}; ` : ''}--dry-image-comparison-position: ${position}%`;
29
+ });
34
30
  }
35
31
 
36
- function updatePosition(clientX: number, clientY: number) {
37
- if (!containerEl) return;
32
+ function updatePosition(clientX: number, clientY: number, containerEl: HTMLElement) {
38
33
  const rect = containerEl.getBoundingClientRect();
39
34
  let pct: number;
40
35
  if (orientation === 'horizontal') {
@@ -47,13 +42,16 @@
47
42
 
48
43
  function onPointerDown(e: PointerEvent) {
49
44
  dragging = true;
50
- (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
51
- updatePosition(e.clientX, e.clientY);
45
+ const handleEl = e.currentTarget as HTMLElement;
46
+ handleEl.setPointerCapture(e.pointerId);
47
+ const containerEl = handleEl.closest<HTMLElement>('[data-image-comparison]');
48
+ if (!containerEl) return;
49
+ updatePosition(e.clientX, e.clientY, containerEl);
52
50
  }
53
51
 
54
52
  function onPointerMove(e: PointerEvent) {
55
53
  if (!dragging) return;
56
- updatePosition(e.clientX, e.clientY);
54
+ updatePosition(e.clientX, e.clientY, e.currentTarget as HTMLElement);
57
55
  }
58
56
 
59
57
  function onPointerUp() {
@@ -70,13 +68,6 @@
70
68
  position = Math.min(position + step, 100);
71
69
  }
72
70
  }
73
-
74
- function applyStyles(node: HTMLElement) {
75
- $effect(() => {
76
- node.style.cssText = style || '';
77
- node.style.setProperty('--dry-image-comparison-position', `${position}%`);
78
- });
79
- }
80
71
  </script>
81
72
 
82
73
  {#snippet defaultHandle()}
@@ -92,7 +83,7 @@
92
83
  {/snippet}
93
84
 
94
85
  <div
95
- {@attach setContainer}
86
+ {@attach syncStyles}
96
87
  class={className}
97
88
  data-image-comparison
98
89
  data-orientation={orientation}
@@ -100,7 +91,6 @@
100
91
  onpointermove={onPointerMove}
101
92
  onpointerup={onPointerUp}
102
93
  {...rest}
103
- use:applyStyles
104
94
  >
105
95
  <div data-part="after" data-ic-layer>
106
96
  {@render after()}
@@ -141,6 +131,8 @@
141
131
  --dry-image-comparison-handle-z-index: 1;
142
132
 
143
133
  position: relative;
134
+ display: grid;
135
+ height: 100%;
144
136
  overflow: hidden;
145
137
  border-radius: var(--dry-image-comparison-radius);
146
138
  user-select: none;
@@ -148,8 +140,8 @@
148
140
  }
149
141
 
150
142
  [data-ic-layer] {
151
- position: absolute;
152
- inset: 0;
143
+ grid-area: 1 / 1;
144
+ min-height: 0;
153
145
  }
154
146
 
155
147
  [data-image-comparison][data-orientation='horizontal'] [data-ic-layer-before] {
@@ -21,6 +21,7 @@
21
21
  data-size={ctx.size}
22
22
  data-disabled={isDisabled || undefined}
23
23
  data-invalid={ctx.invalid || undefined}
24
+ data-orientation={ctx.orientation}
24
25
  {...rest}
25
26
  data-input-group-action
26
27
  class={className}
@@ -47,6 +48,10 @@
47
48
  transition: background-color 160ms ease;
48
49
  }
49
50
 
51
+ [data-input-group-action][data-orientation='horizontal'] {
52
+ grid-column: 5;
53
+ }
54
+
50
55
  [data-input-group-action]:hover:not(:disabled) {
51
56
  background: var(--dry-color-fill-weak);
52
57
  }
@@ -16,6 +16,7 @@
16
16
  data-size={ctx.size}
17
17
  data-disabled={ctx.disabled || undefined}
18
18
  data-invalid={ctx.invalid || undefined}
19
+ data-orientation={ctx.orientation}
19
20
  data-input-group-inputWrap
20
21
  >
21
22
  <input
@@ -30,11 +31,14 @@
30
31
  <style>
31
32
  [data-input-group-inputWrap] {
32
33
  display: grid;
33
- grid-auto-flow: column;
34
- grid-auto-columns: minmax(0, 1fr);
34
+ grid-template-columns: minmax(0, 1fr);
35
35
  align-items: center;
36
36
  }
37
37
 
38
+ [data-input-group-inputWrap][data-orientation='horizontal'] {
39
+ grid-column: 2;
40
+ }
41
+
38
42
  [data-input-group-input] {
39
43
  border: 0;
40
44
  background: transparent;
@@ -44,6 +48,7 @@
44
48
  line-height: 1.4;
45
49
  padding: var(--dry-input-group-padding-y) var(--dry-input-group-padding-x);
46
50
  outline: none;
51
+ box-sizing: border-box;
47
52
  }
48
53
 
49
54
  [data-input-group-input]::placeholder {
@@ -17,6 +17,7 @@
17
17
  data-size={ctx.size}
18
18
  data-disabled={ctx.disabled || undefined}
19
19
  data-invalid={ctx.invalid || undefined}
20
+ data-orientation={ctx.orientation}
20
21
  {...rest}
21
22
  data-input-group-prefix
22
23
  class={className}
@@ -35,4 +36,8 @@
35
36
  color: var(--dry-input-group-muted);
36
37
  white-space: nowrap;
37
38
  }
39
+
40
+ [data-input-group-prefix][data-orientation='horizontal'] {
41
+ grid-column: 1;
42
+ }
38
43
  </style>
@@ -65,8 +65,6 @@
65
65
  --dry-input-group-separator: color-mix(in srgb, var(--dry-input-group-border) 80%, transparent);
66
66
 
67
67
  display: grid;
68
- grid-auto-flow: column;
69
- grid-auto-columns: max-content;
70
68
  align-items: stretch;
71
69
  min-height: 3rem;
72
70
  border: 1px solid var(--dry-input-group-border);
@@ -76,6 +74,16 @@
76
74
  overflow: hidden;
77
75
  }
78
76
 
77
+ [data-input-group-root][data-orientation='horizontal'] {
78
+ grid-template-columns:
79
+ max-content
80
+ minmax(0, 1fr)
81
+ max-content
82
+ max-content
83
+ max-content
84
+ max-content;
85
+ }
86
+
79
87
  [data-input-group-root]:focus-within {
80
88
  border-color: var(--dry-input-group-border-strong);
81
89
  box-shadow: 0 0 0 1px var(--dry-input-group-border-strong);
@@ -19,6 +19,7 @@
19
19
  data-size={ctx.size}
20
20
  data-disabled={ctx.disabled || undefined}
21
21
  data-invalid={ctx.invalid || undefined}
22
+ data-orientation={ctx.orientation}
22
23
  >
23
24
  <select bind:value class={className} data-input-group-select {...rest}>
24
25
  {@render children?.()}
@@ -31,6 +32,10 @@
31
32
  position: relative;
32
33
  }
33
34
 
35
+ [data-input-group-selectWrap][data-orientation='horizontal'] {
36
+ grid-column: 6;
37
+ }
38
+
34
39
  [data-input-group-select] {
35
40
  display: inline-grid;
36
41
  grid-auto-flow: column;
@@ -15,6 +15,7 @@
15
15
  data-size={ctx.size}
16
16
  data-disabled={ctx.disabled || undefined}
17
17
  data-invalid={ctx.invalid || undefined}
18
+ data-orientation={ctx.orientation}
18
19
  {...rest}
19
20
  data-input-group-separator
20
21
  class={className}
@@ -25,4 +26,13 @@
25
26
  align-self: stretch;
26
27
  border-inline-start: 1px solid var(--dry-input-group-separator);
27
28
  }
29
+
30
+ [data-input-group-separator][data-orientation='horizontal'] {
31
+ grid-column: 4;
32
+ }
33
+
34
+ [data-input-group-separator][data-orientation='vertical'] {
35
+ border-inline-start: 0;
36
+ border-top: 1px solid var(--dry-input-group-separator);
37
+ }
28
38
  </style>