@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
@@ -82,8 +82,10 @@
82
82
  <style>
83
83
  [data-dg-pagination] {
84
84
  display: grid;
85
- grid-template-columns: max-content 1fr max-content;
85
+ grid-template-columns: minmax(0, 1fr) max-content minmax(0, 1fr);
86
+ grid-template-areas: 'prev info next';
86
87
  align-items: center;
88
+ column-gap: var(--dry-data-grid-pagination-gap);
87
89
  padding: var(--dry-space-3) var(--dry-data-grid-padding-x);
88
90
  border-top: 1px solid var(--dry-data-grid-border);
89
91
  font-size: var(--dry-type-small-size, var(--dry-type-small-size));
@@ -122,18 +124,34 @@
122
124
  outline-offset: 2px;
123
125
  }
124
126
 
127
+ [data-dg-pagination] button[data-pagination-prev] {
128
+ grid-area: prev;
129
+ justify-self: start;
130
+ }
131
+
132
+ [data-dg-pagination] button[data-pagination-next] {
133
+ grid-area: next;
134
+ justify-self: end;
135
+ }
136
+
125
137
  [data-dg-pagination] button:disabled {
126
138
  opacity: 0.4;
127
139
  cursor: not-allowed;
128
140
  }
129
141
 
130
142
  [data-dg-pagination] [data-pagination-info] {
143
+ grid-area: info;
144
+ justify-self: center;
145
+ text-align: center;
131
146
  font-variant-numeric: tabular-nums;
132
147
  }
133
148
 
134
149
  @container (max-width: 400px) {
135
150
  [data-dg-pagination] {
136
- grid-template-columns: 1fr;
151
+ grid-template-columns: repeat(2, minmax(0, 1fr));
152
+ grid-template-areas:
153
+ 'info info'
154
+ 'prev next';
137
155
  gap: var(--dry-space-2);
138
156
  }
139
157
  }
@@ -214,6 +214,7 @@
214
214
  --dry-data-grid-sort-color: var(--dry-color-fill-brand);
215
215
  --dry-data-grid-pagination-gap: var(--dry-space-2);
216
216
 
217
+ display: grid;
217
218
  container-type: inline-size;
218
219
  overflow-x: auto;
219
220
  }
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
3
  import type { HTMLAttributes } from 'svelte/elements';
4
+ import { SvelteMap } from 'svelte/reactivity';
4
5
  import { setDateFieldCtx, getLocaleFormat, type DateSegmentType } from './context.svelte.js';
5
6
 
6
7
  interface Props extends HTMLAttributes<HTMLDivElement> {
@@ -14,6 +15,12 @@
14
15
  children: Snippet;
15
16
  }
16
17
 
18
+ interface SegmentValues {
19
+ month: number | null;
20
+ day: number | null;
21
+ year: number | null;
22
+ }
23
+
17
24
  let {
18
25
  value = $bindable<Date | null>(null),
19
26
  name,
@@ -27,37 +34,61 @@
27
34
  ...rest
28
35
  }: Props = $props();
29
36
 
30
- let month = $state<number | null>(value ? value.getMonth() + 1 : null);
31
- let day = $state<number | null>(value ? value.getDate() : null);
32
- let year = $state<number | null>(value ? value.getFullYear() : null);
37
+ let draftValues = $state<SegmentValues | null>(null);
33
38
 
34
- // Sync from value prop
35
- $effect(() => {
36
- if (value) {
37
- month = value.getMonth() + 1;
38
- day = value.getDate();
39
- year = value.getFullYear();
39
+ function getSegmentValues(date: Date | null): SegmentValues {
40
+ if (!date) {
41
+ return { month: null, day: null, year: null };
40
42
  }
41
- });
42
43
 
43
- function tryBuildDate() {
44
- if (month !== null && day !== null && year !== null && year >= 1000) {
45
- const d = new Date(year, month - 1, day);
46
- if (d.getMonth() === month - 1 && d.getDate() === day) {
44
+ return {
45
+ month: date.getMonth() + 1,
46
+ day: date.getDate(),
47
+ year: date.getFullYear()
48
+ };
49
+ }
50
+
51
+ function commitSegments(nextValues: SegmentValues) {
52
+ if (
53
+ nextValues.month !== null &&
54
+ nextValues.day !== null &&
55
+ nextValues.year !== null &&
56
+ nextValues.year >= 1000
57
+ ) {
58
+ const d = new Date(nextValues.year, nextValues.month - 1, nextValues.day);
59
+ if (d.getMonth() === nextValues.month - 1 && d.getDate() === nextValues.day) {
47
60
  value = d;
61
+ draftValues = null;
62
+ return;
48
63
  }
49
64
  }
65
+
66
+ draftValues = nextValues;
50
67
  }
51
68
 
52
69
  const localeFormat = $derived(getLocaleFormat(locale));
70
+ const committedValues = $derived(getSegmentValues(value));
71
+ const activeValues = $derived(draftValues ?? committedValues);
53
72
 
54
73
  const segments = $derived(
55
74
  localeFormat.order.map((type) => ({
56
75
  type,
57
- value: type === 'month' ? month : type === 'day' ? day : year
76
+ value:
77
+ type === 'month'
78
+ ? activeValues.month
79
+ : type === 'day'
80
+ ? activeValues.day
81
+ : activeValues.year
58
82
  }))
59
83
  );
60
84
 
85
+ function focusPreferredSegment() {
86
+ const targetType =
87
+ segments.find((segment) => segment.value === null)?.type ?? localeFormat.order[0];
88
+ if (!targetType) return;
89
+ segmentElements.get(targetType)?.focus();
90
+ }
91
+
61
92
  function serializeDateValue(date: Date | null): string {
62
93
  if (!date) return '';
63
94
 
@@ -69,7 +100,7 @@
69
100
  }
70
101
 
71
102
  // Segment element registry for index-based navigation
72
- const segmentElements = new Map<DateSegmentType, HTMLElement>();
103
+ const segmentElements = new SvelteMap<DateSegmentType, HTMLElement>();
73
104
 
74
105
  setDateFieldCtx({
75
106
  get value() {
@@ -97,10 +128,11 @@
97
128
  return segments;
98
129
  },
99
130
  updateSegment(type: DateSegmentType, val: number) {
100
- if (type === 'month') month = val;
101
- else if (type === 'day') day = val;
102
- else if (type === 'year') year = val;
103
- tryBuildDate();
131
+ commitSegments({
132
+ month: type === 'month' ? val : activeValues.month,
133
+ day: type === 'day' ? val : activeValues.day,
134
+ year: type === 'year' ? val : activeValues.year
135
+ });
104
136
  },
105
137
  registerSegment(type: DateSegmentType, el: HTMLElement) {
106
138
  segmentElements.set(type, el);
@@ -119,12 +151,26 @@
119
151
  }
120
152
  }
121
153
  });
154
+
155
+ function handleMousedown(event: MouseEvent) {
156
+ if (disabled) return;
157
+ const target = event.target;
158
+ if (!(target instanceof HTMLElement)) return;
159
+ if (target.closest('[data-df-segment]')) return;
160
+
161
+ event.preventDefault();
162
+ focusPreferredSegment();
163
+ }
122
164
  </script>
123
165
 
124
166
  <div
125
167
  role="group"
126
168
  aria-label="Date"
169
+ data-df-wrapper
170
+ data-df-root
171
+ data-size={size}
127
172
  data-disabled={disabled || undefined}
173
+ onmousedown={handleMousedown}
128
174
  {...rest}
129
175
  class={className}
130
176
  >
@@ -1,7 +1,6 @@
1
1
  <script lang="ts">
2
2
  import type { HTMLAttributes } from 'svelte/elements';
3
3
  import { getDateFieldCtx, type DateSegmentType } from './context.svelte.js';
4
- import { onMount } from 'svelte';
5
4
 
6
5
  interface Props extends HTMLAttributes<HTMLSpanElement> {
7
6
  type: DateSegmentType;
@@ -11,13 +10,6 @@
11
10
 
12
11
  const ctx = getDateFieldCtx();
13
12
 
14
- let el: HTMLSpanElement;
15
-
16
- onMount(() => {
17
- ctx.registerSegment(type, el);
18
- return () => ctx.unregisterSegment(type);
19
- });
20
-
21
13
  const segmentData = $derived(ctx.segments.find((s) => s.type === type));
22
14
 
23
15
  const minValue = $derived(type === 'month' ? 1 : type === 'day' ? 1 : 1000);
@@ -35,6 +27,15 @@
35
27
  let inputBuffer = '';
36
28
  let bufferTimeout: ReturnType<typeof setTimeout>;
37
29
 
30
+ function registerSegment(node: HTMLSpanElement) {
31
+ ctx.registerSegment(type, node);
32
+ return {
33
+ destroy() {
34
+ ctx.unregisterSegment(type);
35
+ }
36
+ };
37
+ }
38
+
38
39
  function increment() {
39
40
  const current = segmentData?.value ?? minValue - 1;
40
41
  const next = current >= maxValue ? minValue : current + 1;
@@ -111,7 +112,7 @@
111
112
  </script>
112
113
 
113
114
  <span
114
- bind:this={el}
115
+ {@attach registerSegment}
115
116
  role="spinbutton"
116
117
  tabindex={ctx.disabled ? undefined : 0}
117
118
  aria-label={type}
@@ -119,6 +120,7 @@
119
120
  aria-valuemax={maxValue}
120
121
  aria-valuenow={segmentData?.value ?? undefined}
121
122
  aria-valuetext={displayValue}
123
+ data-df-segment
122
124
  data-segment={type}
123
125
  data-placeholder={segmentData?.value === null ? '' : undefined}
124
126
  data-disabled={ctx.disabled || undefined}
@@ -13,7 +13,15 @@
13
13
  const display = $derived(separator ?? ctx.separator);
14
14
  </script>
15
15
 
16
- <span aria-hidden="true" data-separator="" {...rest} class={className}>{display}</span>
16
+ <span
17
+ aria-hidden="true"
18
+ data-df-separator
19
+ data-separator=""
20
+ {...rest}
21
+ class={className}
22
+ >
23
+ {display}
24
+ </span>
17
25
 
18
26
  <style>
19
27
  [data-df-separator] {
@@ -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));
@@ -70,38 +80,54 @@
70
80
  }
71
81
  </script>
72
82
 
73
- <div bind:this={containerEl} class={className} {...rest} data-dp-calendar>
83
+ <div {@attach bindContainer} class={className} {...rest} data-dp-calendar>
74
84
  <!-- Calendar header: month/year + navigation -->
75
- <div role="group" aria-label={monthYearLabel}>
76
- <div class="dp-header">
77
- <button type="button" aria-label="Previous month" onclick={() => ctx.prevMonth()}> ‹ </button>
78
- <span aria-live="polite" aria-atomic="true">
85
+ <div role="group" aria-label={monthYearLabel} data-calendar-panel>
86
+ <div class="dp-header" data-calendar-header>
87
+ <button
88
+ type="button"
89
+ aria-label="Previous month"
90
+ data-calendar-nav
91
+ disabled={ctx.disabled}
92
+ onclick={() => ctx.prevMonth()}
93
+ >
94
+
95
+ </button>
96
+ <span aria-live="polite" aria-atomic="true" data-calendar-heading>
79
97
  {monthYearLabel}
80
98
  </span>
81
- <button type="button" aria-label="Next month" onclick={() => ctx.nextMonth()}> › </button>
99
+ <button
100
+ type="button"
101
+ aria-label="Next month"
102
+ data-calendar-nav
103
+ disabled={ctx.disabled}
104
+ onclick={() => ctx.nextMonth()}
105
+ >
106
+
107
+ </button>
82
108
  </div>
83
109
 
84
110
  <!-- Day-of-week header row -->
85
111
  <div role="grid" aria-label={monthYearLabel}>
86
- <div role="row">
87
- {#each weekdayLabels as label}
88
- <div role="columnheader" aria-label={label}>
112
+ <div role="row" data-calendar-row>
113
+ {#each weekdayLabels as label (label)}
114
+ <div role="columnheader" aria-label={label} data-calendar-columnheader>
89
115
  <span aria-hidden="true">{label}</span>
90
116
  </div>
91
117
  {/each}
92
118
  </div>
93
119
 
94
120
  <!-- Calendar day grid -->
95
- {#each weeks as week}
96
- <div role="row">
97
- {#each week as day}
121
+ {#each weeks as week, weekIndex (weekIndex)}
122
+ <div role="row" data-calendar-row>
123
+ {#each week as day (getDayISOString(day))}
98
124
  {@const isCurrent = day.getMonth() === ctx.viewMonth}
99
125
  {@const selected = ctx.value ? isSameDay(day, ctx.value) : false}
100
126
  {@const today = isToday(day)}
101
127
  {@const disabled = isDayDisabled(day)}
102
128
  {@const focused = isSameDay(day, ctx.focusedDate)}
103
129
  {@const isoStr = getDayISOString(day)}
104
- <div role="gridcell">
130
+ <div role="gridcell" data-calendar-cell>
105
131
  <button
106
132
  type="button"
107
133
  tabindex={focused ? 0 : -1}
@@ -112,6 +138,7 @@
112
138
  })}
113
139
  aria-pressed={selected}
114
140
  aria-disabled={disabled}
141
+ data-calendar-day-button
115
142
  data-calendar-day={isoStr}
116
143
  data-today={today ? '' : undefined}
117
144
  data-selected={selected ? '' : undefined}
@@ -132,7 +159,135 @@
132
159
 
133
160
  <style>
134
161
  [data-dp-calendar] {
162
+ --dry-calendar-grid-gap: 1px;
135
163
  container-type: inline-size;
164
+ display: grid;
165
+ gap: var(--dry-space-2);
136
166
  user-select: none;
167
+ color: var(--dry-calendar-header-color, var(--dry-color-text-strong));
168
+ font-family: var(--dry-font-sans);
169
+ }
170
+
171
+ [data-dp-calendar] [data-calendar-panel] {
172
+ display: grid;
173
+ gap: var(--dry-space-2);
174
+ }
175
+
176
+ [data-dp-calendar] [data-calendar-header] {
177
+ display: grid;
178
+ grid-template-columns: auto 1fr auto;
179
+ align-items: center;
180
+ gap: var(--dry-space-2);
181
+ }
182
+
183
+ [data-dp-calendar] [data-calendar-nav] {
184
+ display: inline-grid;
185
+ place-items: center;
186
+ height: var(--dry-space-8);
187
+ aspect-ratio: 1;
188
+ border: 1px solid transparent;
189
+ border-radius: var(--dry-calendar-day-radius, var(--dry-radius-md));
190
+ background: transparent;
191
+ color: var(--dry-calendar-header-color, var(--dry-color-text-strong));
192
+ cursor: pointer;
193
+ transition:
194
+ background var(--dry-duration-fast) var(--dry-ease-default),
195
+ border-color var(--dry-duration-fast) var(--dry-ease-default);
196
+ }
197
+
198
+ [data-dp-calendar] [data-calendar-nav]:hover:not([disabled]) {
199
+ background: var(--dry-calendar-day-hover-bg, var(--dry-color-bg-raised));
200
+ border-color: var(--dry-color-stroke-strong);
201
+ }
202
+
203
+ [data-dp-calendar] [data-calendar-nav]:focus-visible {
204
+ outline: 2px solid var(--dry-color-focus-ring);
205
+ outline-offset: 1px;
206
+ }
207
+
208
+ [data-dp-calendar] [data-calendar-heading] {
209
+ font-size: var(--dry-type-small-size, var(--dry-type-small-size));
210
+ font-weight: 600;
211
+ letter-spacing: -0.01em;
212
+ }
213
+
214
+ [data-dp-calendar] [role='grid'] {
215
+ display: grid;
216
+ gap: var(--dry-calendar-grid-gap);
217
+ }
218
+
219
+ [data-dp-calendar] [data-calendar-row] {
220
+ display: grid;
221
+ grid-template-columns: repeat(7, minmax(0, 1fr));
222
+ gap: var(--dry-calendar-grid-gap);
223
+ }
224
+
225
+ [data-dp-calendar] [data-calendar-columnheader] {
226
+ display: grid;
227
+ place-items: center;
228
+ min-height: var(--dry-space-8);
229
+ font-size: var(--dry-type-tiny-size, var(--dry-type-tiny-size));
230
+ color: var(--dry-calendar-muted-color, var(--dry-color-text-weak));
231
+ text-transform: uppercase;
232
+ letter-spacing: 0.04em;
233
+ }
234
+
235
+ [data-dp-calendar] [data-calendar-cell] {
236
+ display: grid;
237
+ grid-template-columns: var(--dry-calendar-day-size, 2.25rem);
238
+ place-items: center;
239
+ }
240
+
241
+ [data-dp-calendar] [data-calendar-day-button] {
242
+ display: inline-grid;
243
+ place-items: center;
244
+ min-height: var(--dry-calendar-day-size, 2.25rem);
245
+ aspect-ratio: 1;
246
+ border: none;
247
+ border-radius: var(--dry-calendar-day-radius, var(--dry-radius-md));
248
+ background: transparent;
249
+ color: var(--dry-color-text-strong);
250
+ font: inherit;
251
+ font-size: var(--dry-type-small-size, var(--dry-type-small-size));
252
+ font-variant-numeric: tabular-nums;
253
+ cursor: pointer;
254
+ transition:
255
+ background var(--dry-duration-fast) var(--dry-ease-default),
256
+ color var(--dry-duration-fast) var(--dry-ease-default);
257
+ }
258
+
259
+ [data-dp-calendar] [data-calendar-day-button]:hover:not([data-disabled]) {
260
+ background: var(--dry-calendar-day-hover-bg, var(--dry-color-bg-raised));
261
+ }
262
+
263
+ [data-dp-calendar] [data-calendar-day-button]:focus-visible {
264
+ outline: 2px solid var(--dry-color-focus-ring);
265
+ outline-offset: 1px;
266
+ }
267
+
268
+ [data-dp-calendar] [data-calendar-day-button][data-today]:not([data-selected]) {
269
+ color: var(--dry-calendar-today-color, var(--dry-color-fill-brand));
270
+ font-weight: 600;
271
+ }
272
+
273
+ [data-dp-calendar] [data-calendar-day-button][data-selected] {
274
+ background: var(--dry-calendar-selected-bg, var(--dry-color-fill-brand));
275
+ color: var(--dry-calendar-selected-color, var(--dry-color-on-brand));
276
+ font-weight: 600;
277
+ }
278
+
279
+ [data-dp-calendar] [data-calendar-day-button][data-selected]:hover:not([data-disabled]) {
280
+ background: var(--dry-calendar-selected-hover-bg, var(--dry-color-fill-brand-hover));
281
+ }
282
+
283
+ [data-dp-calendar] [data-calendar-day-button][data-outside-month] {
284
+ color: var(--dry-calendar-outside-color, var(--dry-color-text-weak));
285
+ opacity: 0.6;
286
+ }
287
+
288
+ [data-dp-calendar] [data-calendar-day-button][data-disabled] {
289
+ cursor: not-allowed;
290
+ opacity: 0.4;
291
+ pointer-events: none;
137
292
  }
138
293
  </style>
@@ -61,6 +61,7 @@
61
61
  {displayText || placeholder}
62
62
  </span>
63
63
  {/if}
64
+ <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="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
64
65
  </button>
65
66
 
66
67
  <style>
@@ -94,15 +95,9 @@
94
95
  transform var(--dry-duration-fast) var(--dry-ease-default);
95
96
  }
96
97
 
97
- [data-dp-trigger]::after {
98
- content: '';
99
- aspect-ratio: 1;
98
+ [data-dp-trigger] [data-indicator] {
100
99
  height: 1rem;
101
- background: currentColor;
102
- mask-image: 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='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
103
- mask-size: contain;
104
- mask-repeat: no-repeat;
105
- mask-position: center;
100
+ aspect-ratio: 1;
106
101
  opacity: 0.6;
107
102
  }
108
103