@cahyo-dimas/freeday 1.12.0 → 1.13.1
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.
- package/CHANGELOG.md +33 -0
- package/README.id.md +1 -1
- package/README.md +1 -1
- package/adapters/react/components/FdyCombo.tsx +4 -0
- package/adapters/react/components/FdyDatepicker.tsx +36 -4
- package/adapters/vue/components/FdyCombo.vue +4 -0
- package/adapters/vue/components/FdyDatepicker.vue +38 -4
- package/dist/freeday.bundle.css +8 -0
- package/dist/freeday.css +8 -0
- package/package.json +1 -1
- package/src/components/datepicker.css +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,39 @@
|
|
|
3
3
|
Semua perubahan penting dicatat di sini. Format longgar mengikuti
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/); tiap versi = git tag.
|
|
5
5
|
|
|
6
|
+
## [1.13.1] — 2026-08-01
|
|
7
|
+
### Fixed
|
|
8
|
+
- **`FdyCombo` can be selected with the mouse again (#38).** Clicking an option did nothing — the
|
|
9
|
+
listbox closed and no `update:modelValue` fired (keyboard select still worked, which is why a
|
|
10
|
+
keyboard-only smoke test missed it). The option `<li>` isn't focusable, so a `mousedown` moved focus
|
|
11
|
+
off the combobox button; the root's `focusout` handler then closed the list — removing the `<li>` —
|
|
12
|
+
*before* `mouseup`, so the browser never generated a `click` and `choose()` was never reached. Added
|
|
13
|
+
`@mousedown.prevent` (Vue) / `onMouseDown` `preventDefault` (React) on the option so focus stays on the
|
|
14
|
+
button and the click lands — the same pattern the sibling `FdyDatepicker` / `FdyAutocomplete` (and the
|
|
15
|
+
vanilla `freeday-select.js`, fixed in v1.6.1) already use. Both adapters; no API change; keyboard and
|
|
16
|
+
hover paths untouched. Verified with trusted CDP mouse events (a synthetic `dispatchEvent` won't
|
|
17
|
+
reproduce it — untrusted events run no default action, so focus never moves).
|
|
18
|
+
|
|
19
|
+
## [1.13.0] — 2026-07-30
|
|
20
|
+
### Added
|
|
21
|
+
- **`FdyDatepicker` clear affordance — an optional date can now be unset (#37A).** A new `clearable`
|
|
22
|
+
prop renders a small × button in the trigger (overlaid in the calendar-icon slot) whenever a date is
|
|
23
|
+
set, emitting `''` (`update:modelValue` + `change` in Vue, `onChange('')` in React) to return to
|
|
24
|
+
empty — closing a functional regression vs the native `<input type="date">`, which offered a clear
|
|
25
|
+
control. Off by default; both adapters. Verified in-browser: the × is right-aligned in the icon slot,
|
|
26
|
+
vertically centred, hides the calendar icon while shown, and never overlaps the value text (even a
|
|
27
|
+
long, ellipsised one).
|
|
28
|
+
- **`FdyDatepicker` month-nav labels are now overridable (#37B).** The previous/next-month `aria-label`s
|
|
29
|
+
were hardcoded, leaking to every screen-reader user with no way to change them; added
|
|
30
|
+
`prevMonthLabel` / `nextMonthLabel` props (plus `clearLabel` for the new × button). Month and weekday
|
|
31
|
+
names already localise via `Intl` + the `locale` prop.
|
|
32
|
+
### Changed
|
|
33
|
+
- **`FdyDatepicker` default UI strings are now English** (`Select date` placeholder, `Previous month` /
|
|
34
|
+
`Next month` nav labels) instead of Indonesian, matching the kit's English-first public docs. Pass
|
|
35
|
+
`placeholder` / `prevMonthLabel` / `nextMonthLabel` for other languages. Scope is the Vue + React
|
|
36
|
+
`FdyDatepicker` adapters only — the vanilla `freeday-datepicker.js` enhancer (used by the Indonesian
|
|
37
|
+
docs demos) keeps its Indonesian defaults.
|
|
38
|
+
|
|
6
39
|
## [1.12.0] — 2026-07-29
|
|
7
40
|
### Added
|
|
8
41
|
- **Chart colour overrides can now name a categorical palette slot (#36).** `data-fdy-colors` (and the
|
package/README.id.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **Lebih banyak _free day_ buat dev — UI kit-nya sudah siap pakai.**
|
|
6
6
|
|
|
7
7
|
[](https://cahyo-dimas.github.io/freeday-ui-kit/)
|
|
8
|
-
[](https://github.com/cahyo-dimas/freeday-ui-kit/tree/v1.13.1)
|
|
9
9
|
|
|
10
10
|
UI KIT yang token-driven & framework-agnostic — satu sumber kebenaran untuk warna, tipografi,
|
|
11
11
|
spasi, dan komponen. Blueprint: `docs/superpowers/specs/2026-07-21-freeday-ui-kit-design.md`.
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **More free days for devs — the UI kit is ready to use.**
|
|
6
6
|
|
|
7
7
|
[](https://cahyo-dimas.github.io/freeday-ui-kit/)
|
|
8
|
-
[](https://github.com/cahyo-dimas/freeday-ui-kit/tree/v1.13.1)
|
|
9
9
|
|
|
10
10
|
A token-driven, framework-agnostic UI kit — one source of truth for color, typography,
|
|
11
11
|
spacing, and components. Blueprint: `docs/superpowers/specs/2026-07-21-freeday-ui-kit-design.md`.
|
|
@@ -148,12 +148,16 @@ export function FdyCombo<T extends string>(props: FdyComboProps<T>): JSX.Element
|
|
|
148
148
|
</button>
|
|
149
149
|
<ul id={listboxId} ref={listboxRef} className="fdy-combo__listbox" role="listbox" hidden={!open}>
|
|
150
150
|
{props.options.map((opt: FdyComboOption<T>, i: number): JSX.Element => (
|
|
151
|
+
// onMouseDown preventDefault keeps focus on the button: the option <li> isn't focusable, so a
|
|
152
|
+
// plain mousedown moves focus out of the combo, fires onBlur (focusout), and closes the list
|
|
153
|
+
// before the click lands. Same pattern as FdyDatepicker/FdyAutocomplete.
|
|
151
154
|
<li
|
|
152
155
|
id={optionId(i)}
|
|
153
156
|
key={opt.value}
|
|
154
157
|
className={i === highlighted ? 'fdy-combo__option is-highlighted' : 'fdy-combo__option'}
|
|
155
158
|
role="option"
|
|
156
159
|
aria-selected={opt.value === props.value}
|
|
160
|
+
onMouseDown={(e: React.MouseEvent): void => e.preventDefault()}
|
|
157
161
|
onClick={(): void => choose(i)}
|
|
158
162
|
onMouseMove={(): void => setHighlight(i)}
|
|
159
163
|
>
|
|
@@ -33,6 +33,14 @@ export interface FdyDatepickerProps {
|
|
|
33
33
|
describedby?: string;
|
|
34
34
|
id?: string;
|
|
35
35
|
ariaLabelledby?: string;
|
|
36
|
+
/** Show a clear (×) button in the trigger when a date is set, so an optional date can be unset. Calls onChange('') to reset. Off by default. */
|
|
37
|
+
clearable?: boolean;
|
|
38
|
+
/** aria-label for the previous-month nav button. Default 'Previous month' — override for non-English UIs (month/weekday names already follow `locale`). */
|
|
39
|
+
prevMonthLabel?: string;
|
|
40
|
+
/** aria-label for the next-month nav button. Default 'Next month'. */
|
|
41
|
+
nextMonthLabel?: string;
|
|
42
|
+
/** aria-label for the clear button (when `clearable`). Default 'Clear date'. */
|
|
43
|
+
clearLabel?: string;
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
function pad(n: number): string {
|
|
@@ -109,7 +117,11 @@ export function FdyDatepicker(props: FdyDatepickerProps): JSX.Element {
|
|
|
109
117
|
const maxDate: Date | null = useMemo((): Date | null => parseISO(props.max), [props.max]);
|
|
110
118
|
const isDisabled: boolean = props.disabled === true;
|
|
111
119
|
const isInvalid: boolean = props.invalid === true;
|
|
112
|
-
const displayPlaceholder: string = props.placeholder ?? '
|
|
120
|
+
const displayPlaceholder: string = props.placeholder ?? 'Select date';
|
|
121
|
+
const showClear: boolean = props.clearable === true && selectedDate !== null && !isDisabled;
|
|
122
|
+
const prevMonthLabelText: string = props.prevMonthLabel ?? 'Previous month';
|
|
123
|
+
const nextMonthLabelText: string = props.nextMonthLabel ?? 'Next month';
|
|
124
|
+
const clearLabelText: string = props.clearLabel ?? 'Clear date';
|
|
113
125
|
|
|
114
126
|
const [viewMonth, setViewMonth] = useState<Date>((): Date => startOfMonth(parseISO(props.value) ?? new Date()));
|
|
115
127
|
const [focusDate, setFocusDate] = useState<Date>((): Date => parseISO(props.value) ?? new Date());
|
|
@@ -203,6 +215,13 @@ export function FdyDatepicker(props: FdyDatepickerProps): JSX.Element {
|
|
|
203
215
|
closePanel(true);
|
|
204
216
|
}
|
|
205
217
|
|
|
218
|
+
// Clear (reset to empty). Calls onChange('') — parseISO('') is null, so the placeholder shows again.
|
|
219
|
+
function clearValue(): void {
|
|
220
|
+
props.onChange('');
|
|
221
|
+
setOpen(false);
|
|
222
|
+
triggerRef.current?.focus();
|
|
223
|
+
}
|
|
224
|
+
|
|
206
225
|
function openPanel(): void {
|
|
207
226
|
if (isDisabled || open) return;
|
|
208
227
|
const next: Date = selectedDate ?? focusDate ?? new Date();
|
|
@@ -307,21 +326,34 @@ export function FdyDatepicker(props: FdyDatepickerProps): JSX.Element {
|
|
|
307
326
|
<span className={selectedDate === null ? 'fdy-datepicker__value fdy-datepicker__value--placeholder' : 'fdy-datepicker__value'}>
|
|
308
327
|
{displayValue}
|
|
309
328
|
</span>
|
|
310
|
-
<span className=
|
|
329
|
+
<span className={showClear ? 'fdy-datepicker__icon is-hidden' : 'fdy-datepicker__icon'} aria-hidden="true">
|
|
311
330
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
|
|
312
331
|
<rect x="3" y="4" width="18" height="18" rx="2"></rect>
|
|
313
332
|
<path d="M16 2v4M8 2v4M3 10h18"></path>
|
|
314
333
|
</svg>
|
|
315
334
|
</span>
|
|
316
335
|
</button>
|
|
336
|
+
{showClear ? (
|
|
337
|
+
<button
|
|
338
|
+
type="button"
|
|
339
|
+
className="fdy-datepicker__clear"
|
|
340
|
+
aria-label={clearLabelText}
|
|
341
|
+
onMouseDown={(e: React.MouseEvent): void => e.preventDefault()}
|
|
342
|
+
onClick={clearValue}
|
|
343
|
+
>
|
|
344
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
|
|
345
|
+
<path d="M18 6 6 18M6 6l12 12"></path>
|
|
346
|
+
</svg>
|
|
347
|
+
</button>
|
|
348
|
+
) : null}
|
|
317
349
|
|
|
318
350
|
<div ref={panelRef} className="fdy-datepicker__panel" role="dialog" aria-modal="false" aria-labelledby={titleId} hidden={!open}>
|
|
319
351
|
<div className="fdy-cal__head">
|
|
320
|
-
<button type="button" className="fdy-cal__nav" aria-label=
|
|
352
|
+
<button type="button" className="fdy-cal__nav" aria-label={prevMonthLabelText} onClick={(): void => setViewMonth(addMonths(viewMonth, -1))}>
|
|
321
353
|
‹
|
|
322
354
|
</button>
|
|
323
355
|
<div id={titleId} className="fdy-cal__title">{monthFmt.format(viewMonth)}</div>
|
|
324
|
-
<button type="button" className="fdy-cal__nav" aria-label=
|
|
356
|
+
<button type="button" className="fdy-cal__nav" aria-label={nextMonthLabelText} onClick={(): void => setViewMonth(addMonths(viewMonth, 1))}>
|
|
325
357
|
›
|
|
326
358
|
</button>
|
|
327
359
|
</div>
|
|
@@ -214,6 +214,9 @@ onBeforeUnmount((): void => {
|
|
|
214
214
|
<span class="fdy-combo__value" :class="{ 'fdy-combo__value--placeholder': isPlaceholder }">{{ selectedLabel }}</span>
|
|
215
215
|
</button>
|
|
216
216
|
<ul :id="listboxId" ref="listboxEl" class="fdy-combo__listbox" role="listbox" popover="manual" :hidden="!open">
|
|
217
|
+
<!-- @mousedown.prevent keeps focus on the button: the option <li> isn't focusable, so a plain
|
|
218
|
+
mousedown moves focus out of the combo, fires @focusout, and closes the list before the click
|
|
219
|
+
lands — mouse-select would silently do nothing. Same pattern as FdyDatepicker/FdyAutocomplete. -->
|
|
217
220
|
<li
|
|
218
221
|
v-for="(opt, i) in options"
|
|
219
222
|
:id="optionId(i)"
|
|
@@ -222,6 +225,7 @@ onBeforeUnmount((): void => {
|
|
|
222
225
|
:class="{ 'is-highlighted': i === highlighted }"
|
|
223
226
|
role="option"
|
|
224
227
|
:aria-selected="opt.value === modelValue"
|
|
228
|
+
@mousedown.prevent
|
|
225
229
|
@click="choose(i)"
|
|
226
230
|
@mousemove="setHighlight(i)"
|
|
227
231
|
>
|
|
@@ -35,6 +35,14 @@ const props = defineProps<{
|
|
|
35
35
|
describedby?: string;
|
|
36
36
|
id?: string;
|
|
37
37
|
ariaLabelledby?: string;
|
|
38
|
+
/** Show a clear (×) button in the trigger when a date is set, so an optional date can be unset. Emits `''` via update:modelValue + change. Off by default. */
|
|
39
|
+
clearable?: boolean;
|
|
40
|
+
/** aria-label for the previous-month nav button. Default 'Previous month' — override for non-English UIs (month/weekday names already follow `locale`). */
|
|
41
|
+
prevMonthLabel?: string;
|
|
42
|
+
/** aria-label for the next-month nav button. Default 'Next month'. */
|
|
43
|
+
nextMonthLabel?: string;
|
|
44
|
+
/** aria-label for the clear button (when `clearable`). Default 'Clear date'. */
|
|
45
|
+
clearLabel?: string;
|
|
38
46
|
}>();
|
|
39
47
|
|
|
40
48
|
const emit = defineEmits<{
|
|
@@ -98,7 +106,13 @@ const minDate: ComputedRef<Date | null> = computed((): Date | null => parseISO(p
|
|
|
98
106
|
const maxDate: ComputedRef<Date | null> = computed((): Date | null => parseISO(props.max));
|
|
99
107
|
const isDisabled: ComputedRef<boolean> = computed((): boolean => props.disabled === true);
|
|
100
108
|
const isInvalid: ComputedRef<boolean> = computed((): boolean => props.invalid === true);
|
|
101
|
-
const displayPlaceholder: ComputedRef<string> = computed((): string => props.placeholder ?? '
|
|
109
|
+
const displayPlaceholder: ComputedRef<string> = computed((): string => props.placeholder ?? 'Select date');
|
|
110
|
+
const showClear: ComputedRef<boolean> = computed(
|
|
111
|
+
(): boolean => props.clearable === true && selectedDate.value !== null && isDisabled.value === false,
|
|
112
|
+
);
|
|
113
|
+
const prevMonthLabelText: ComputedRef<string> = computed((): string => props.prevMonthLabel ?? 'Previous month');
|
|
114
|
+
const nextMonthLabelText: ComputedRef<string> = computed((): string => props.nextMonthLabel ?? 'Next month');
|
|
115
|
+
const clearLabelText: ComputedRef<string> = computed((): string => props.clearLabel ?? 'Clear date');
|
|
102
116
|
|
|
103
117
|
const view: Ref<Date> = ref(startOfMonth(selectedDate.value ?? new Date()));
|
|
104
118
|
const focusDate: Ref<Date> = ref(selectedDate.value ?? new Date());
|
|
@@ -188,6 +202,14 @@ function pick(d: Date): void {
|
|
|
188
202
|
closePanel(true);
|
|
189
203
|
}
|
|
190
204
|
|
|
205
|
+
// Clear (reset to empty). Emits '' — parseISO('') is null, so the placeholder shows again.
|
|
206
|
+
function clearValue(): void {
|
|
207
|
+
emit('update:modelValue', '');
|
|
208
|
+
emit('change', '');
|
|
209
|
+
open.value = false;
|
|
210
|
+
triggerEl.value?.focus();
|
|
211
|
+
}
|
|
212
|
+
|
|
191
213
|
function openPanel(): void {
|
|
192
214
|
if (isDisabled.value || open.value) return;
|
|
193
215
|
focusDate.value = selectedDate.value ?? focusDate.value ?? new Date();
|
|
@@ -297,19 +319,31 @@ onBeforeUnmount((): void => {
|
|
|
297
319
|
@click="toggle"
|
|
298
320
|
>
|
|
299
321
|
<span class="fdy-datepicker__value" :class="{ 'fdy-datepicker__value--placeholder': selectedDate === null }">{{ displayValue }}</span>
|
|
300
|
-
<span class="fdy-datepicker__icon" aria-hidden="true">
|
|
322
|
+
<span class="fdy-datepicker__icon" :class="{ 'is-hidden': showClear }" aria-hidden="true">
|
|
301
323
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
302
324
|
<rect x="3" y="4" width="18" height="18" rx="2"></rect>
|
|
303
325
|
<path d="M16 2v4M8 2v4M3 10h18"></path>
|
|
304
326
|
</svg>
|
|
305
327
|
</span>
|
|
306
328
|
</button>
|
|
329
|
+
<button
|
|
330
|
+
v-if="showClear"
|
|
331
|
+
type="button"
|
|
332
|
+
class="fdy-datepicker__clear"
|
|
333
|
+
:aria-label="clearLabelText"
|
|
334
|
+
@mousedown.prevent
|
|
335
|
+
@click="clearValue"
|
|
336
|
+
>
|
|
337
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
338
|
+
<path d="M18 6 6 18M6 6l12 12"></path>
|
|
339
|
+
</svg>
|
|
340
|
+
</button>
|
|
307
341
|
|
|
308
342
|
<div ref="panelEl" class="fdy-datepicker__panel" role="dialog" aria-modal="false" popover="manual" :aria-labelledby="titleId" :hidden="!open">
|
|
309
343
|
<div class="fdy-cal__head">
|
|
310
|
-
<button type="button" class="fdy-cal__nav" aria-label="
|
|
344
|
+
<button type="button" class="fdy-cal__nav" :aria-label="prevMonthLabelText" @click="view = addMonths(view, -1)">‹</button>
|
|
311
345
|
<div :id="titleId" class="fdy-cal__title">{{ monthFmt.format(view) }}</div>
|
|
312
|
-
<button type="button" class="fdy-cal__nav" aria-label="
|
|
346
|
+
<button type="button" class="fdy-cal__nav" :aria-label="nextMonthLabelText" @click="view = addMonths(view, 1)">›</button>
|
|
313
347
|
</div>
|
|
314
348
|
<div class="fdy-cal__grid" role="grid" :aria-labelledby="titleId" @keydown="onGridKeydown">
|
|
315
349
|
<div v-for="w in weekdayHeaders" :key="w" class="fdy-cal__dow" role="columnheader" :aria-label="w">{{ w }}</div>
|
package/dist/freeday.bundle.css
CHANGED
|
@@ -848,6 +848,14 @@ a { color: var(--color-primary); }
|
|
|
848
848
|
.fdy-datepicker__value--placeholder{color:var(--color-text-subtle);}
|
|
849
849
|
.fdy-datepicker__icon{flex:none;display:inline-flex;color:var(--color-text-subtle);}
|
|
850
850
|
.fdy-datepicker__icon svg{display:block;width:1.05rem;height:1.05rem;}
|
|
851
|
+
/* Clearable: a reset button overlaid in the icon slot (the trigger is itself a <button>, so the
|
|
852
|
+
clear control is a sibling, not a child). Shown only when clearable + a date is set; the calendar
|
|
853
|
+
icon is hidden (kept in flow so the value's ellipsis boundary doesn't shift). */
|
|
854
|
+
.fdy-datepicker__icon.is-hidden{visibility:hidden;}
|
|
855
|
+
.fdy-datepicker__clear{position:absolute;top:50%;right:var(--space-3);transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:1.15rem;height:1.15rem;padding:0;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-subtle);cursor:pointer;transition:color var(--dur-fast) var(--ease-standard),background var(--dur-fast) var(--ease-standard);}
|
|
856
|
+
.fdy-datepicker__clear:hover{color:var(--color-text);background:var(--color-surface-2);}
|
|
857
|
+
.fdy-datepicker__clear:focus-visible{outline:none;color:var(--color-text);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
|
|
858
|
+
.fdy-datepicker__clear svg{display:block;width:.9rem;height:.9rem;}
|
|
851
859
|
|
|
852
860
|
.fdy-datepicker__panel{position:absolute;top:calc(100% + var(--space-1));left:0;z-index:130;padding:var(--space-3);background:var(--color-surface);color:var(--color-text);border:var(--bw) solid var(--color-border-strong);border-radius:var(--radius-md);box-shadow:var(--shadow-3);}
|
|
853
861
|
.fdy-datepicker__panel[hidden]{display:none;}
|
package/dist/freeday.css
CHANGED
|
@@ -503,6 +503,14 @@ a { color: var(--color-primary); }
|
|
|
503
503
|
.fdy-datepicker__value--placeholder{color:var(--color-text-subtle);}
|
|
504
504
|
.fdy-datepicker__icon{flex:none;display:inline-flex;color:var(--color-text-subtle);}
|
|
505
505
|
.fdy-datepicker__icon svg{display:block;width:1.05rem;height:1.05rem;}
|
|
506
|
+
/* Clearable: a reset button overlaid in the icon slot (the trigger is itself a <button>, so the
|
|
507
|
+
clear control is a sibling, not a child). Shown only when clearable + a date is set; the calendar
|
|
508
|
+
icon is hidden (kept in flow so the value's ellipsis boundary doesn't shift). */
|
|
509
|
+
.fdy-datepicker__icon.is-hidden{visibility:hidden;}
|
|
510
|
+
.fdy-datepicker__clear{position:absolute;top:50%;right:var(--space-3);transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:1.15rem;height:1.15rem;padding:0;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-subtle);cursor:pointer;transition:color var(--dur-fast) var(--ease-standard),background var(--dur-fast) var(--ease-standard);}
|
|
511
|
+
.fdy-datepicker__clear:hover{color:var(--color-text);background:var(--color-surface-2);}
|
|
512
|
+
.fdy-datepicker__clear:focus-visible{outline:none;color:var(--color-text);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
|
|
513
|
+
.fdy-datepicker__clear svg{display:block;width:.9rem;height:.9rem;}
|
|
506
514
|
|
|
507
515
|
.fdy-datepicker__panel{position:absolute;top:calc(100% + var(--space-1));left:0;z-index:130;padding:var(--space-3);background:var(--color-surface);color:var(--color-text);border:var(--bw) solid var(--color-border-strong);border-radius:var(--radius-md);box-shadow:var(--shadow-3);}
|
|
508
516
|
.fdy-datepicker__panel[hidden]{display:none;}
|
package/package.json
CHANGED
|
@@ -11,6 +11,14 @@
|
|
|
11
11
|
.fdy-datepicker__value--placeholder{color:var(--color-text-subtle);}
|
|
12
12
|
.fdy-datepicker__icon{flex:none;display:inline-flex;color:var(--color-text-subtle);}
|
|
13
13
|
.fdy-datepicker__icon svg{display:block;width:1.05rem;height:1.05rem;}
|
|
14
|
+
/* Clearable: a reset button overlaid in the icon slot (the trigger is itself a <button>, so the
|
|
15
|
+
clear control is a sibling, not a child). Shown only when clearable + a date is set; the calendar
|
|
16
|
+
icon is hidden (kept in flow so the value's ellipsis boundary doesn't shift). */
|
|
17
|
+
.fdy-datepicker__icon.is-hidden{visibility:hidden;}
|
|
18
|
+
.fdy-datepicker__clear{position:absolute;top:50%;right:var(--space-3);transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:1.15rem;height:1.15rem;padding:0;border:0;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-subtle);cursor:pointer;transition:color var(--dur-fast) var(--ease-standard),background var(--dur-fast) var(--ease-standard);}
|
|
19
|
+
.fdy-datepicker__clear:hover{color:var(--color-text);background:var(--color-surface-2);}
|
|
20
|
+
.fdy-datepicker__clear:focus-visible{outline:none;color:var(--color-text);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary) 26%,transparent);}
|
|
21
|
+
.fdy-datepicker__clear svg{display:block;width:.9rem;height:.9rem;}
|
|
14
22
|
|
|
15
23
|
.fdy-datepicker__panel{position:absolute;top:calc(100% + var(--space-1));left:0;z-index:130;padding:var(--space-3);background:var(--color-surface);color:var(--color-text);border:var(--bw) solid var(--color-border-strong);border-radius:var(--radius-md);box-shadow:var(--shadow-3);}
|
|
16
24
|
.fdy-datepicker__panel[hidden]{display:none;}
|