UNPKG

adwaveui

Version:

Interactive Web Components inspired by the Gtk Adwaita theme.

543 lines (541 loc) 15.9 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // src/components/calendar/calendar.tsx import "../../base-elements.mjs"; import { sig } from "@ncpa0cpl/vanilla-jsx/signals"; import { Button, Typography } from "adwavecss"; import { customElement } from "wc_toolkit"; import { Dt } from "./date.mjs"; import { Fragment, jsx, jsxs } from "@ncpa0cpl/vanilla-jsx/jsx-runtime"; function Btn({ flat, color, disabled, linked, pill, toggled, shape, ...props }) { let cls = {}; if (typeof props.class == "object") { Object.assign(cls, props.class); } else if (Array.isArray(props.class)) { for (const elem of props.class) { cls[elem] = true; } } else if (typeof props.class === "string") { cls[props.class] = true; } cls[Button.className({ flat, color, disabled, linked, pill, toggled, shape })] = true; return /* @__PURE__ */ jsx( "button", { ...props, class: cls } ); } __name(Btn, "Btn"); function strBool(s) { return s.derive((s2) => s2 ? "true" : "false"); } __name(strBool, "strBool"); var DateChangeEvent = class extends Event { static { __name(this, "DateChangeEvent"); } constructor(type, value) { super("change", { bubbles: true, cancelable: true }); this.value = value; } }; var DateModeChangeEvent = class extends Event { static { __name(this, "DateModeChangeEvent"); } constructor(type, value) { super("modechange", { bubbles: true, cancelable: true }); this.value = value; } }; var DateYearSelectEvent = class extends Event { static { __name(this, "DateYearSelectEvent"); } constructor(type, value) { super("yearselected", { bubbles: true, cancelable: true }); this.value = value; } }; var DateMonthSelectEvent = class extends Event { static { __name(this, "DateMonthSelectEvent"); } constructor(type, value) { super("monthselected", { bubbles: true, cancelable: true }); this.value = value; } }; var DateMonthArrowPressEvent = class extends Event { static { __name(this, "DateMonthArrowPressEvent"); } constructor(type, value) { super("montharrowpress", { bubbles: true, cancelable: true }); this.value = value; } }; var { CustomElement } = customElement("adw-calendar").attributes({ value: "string", defaultValue: "string", locale: "string", name: "string", form: "string" }).events({ "change": DateChangeEvent, "yearselected": DateYearSelectEvent, "monthselected": DateMonthSelectEvent, "modechange": DateModeChangeEvent, "montharrowpress": DateMonthArrowPressEvent }).context((attr) => { const selectedDate = sig.derive( attr.value.signal, attr.locale.signal, (v, locale) => { if (v && Dt.isParsable(v)) { return Dt.parse(v).setLocale(locale ?? navigator.language); } return new Dt().setLocale(locale ?? navigator.language); } ); return { selectedDate, visibleDate: sig(selectedDate.get().clone()), selectMode: sig("day"), yearsPage: sig(0) }; }).methods((api) => { return { setYear(y) { api.context.visibleDate.dispatch((d) => { d = d.clone(); d.setYear(y); return d; }); }, setMonth(m) { api.context.visibleDate.dispatch((d) => { d = d.clone(); d.setMonth(m); return d; }); }, nextMonth() { const m = api.context.visibleDate.get().month(); if (m === 12) { const y = api.context.visibleDate.get().year(); this.setYear(y + 1); this.setMonth(1); return; } this.setMonth(m + 1); }, prevMonth() { const m = api.context.visibleDate.get().month(); if (m === 1) { const y = api.context.visibleDate.get().year(); this.setYear(y - 1); this.setMonth(12); return; } this.setMonth(m - 1); }, nextYearPage() { api.context.yearsPage.dispatch((p) => p + 1); }, prevYearPage() { api.context.yearsPage.dispatch((p) => p - 1); }, _showYearSelection(e) { api.emitEvent( "modechange", "year" ).onCommit(() => { e.target.blur(); api.context.yearsPage.dispatch(0); api.context.selectMode.dispatch("year"); }); }, _showMonthSelection(e) { api.emitEvent("modechange", "month").onCommit(() => { e.target.blur(); api.context.selectMode.dispatch("month"); }); }, _updateLocale() { api.context.visibleDate.dispatch((d) => { const l = api.attribute.locale.get(); if (l != null) { return d.clone().setLocale(l); } return d; }); }, _handleDateSelect(date) { api.emitEvent("change", date.jsDate()).onCommit(() => { api.attribute.value.set(date.clone().setHour(12, 0, 0).iso()); }); }, _handleYearSelect(e, y) { api.emitEvent("yearselected", y).onCommit(() => { e.target.blur(); this.setYear(y); api.emitEvent("modechange", "day").onCommit(() => { api.context.selectMode.dispatch("day"); }); }); }, _handleMonthSelect(e, m) { api.emitEvent("monthselected", m).onCommit(() => { e.target.blur(); this.setMonth(m); api.emitEvent("modechange", "day").onCommit(() => { api.context.selectMode.dispatch("day"); }); }); }, _handlePrevMonthPress(e) { api.emitEvent("montharrowpress", "prev").onCommit(() => { this.prevMonth(); }); }, _handleNextMonthPress(e) { api.emitEvent("montharrowpress", "next").onCommit(() => { this.nextMonth(); }); } }; }).connected((api) => { const { selectedDate, visibleDate } = api.context; if (api.attribute.value.get() == null && api.attribute.defaultValue.get() != null) { api.attribute.value.set(api.attribute.defaultValue.get()); } visibleDate.dispatch(selectedDate.get().clone()); api.method._updateLocale(); api.onChange([api.attribute.locale], () => { api.method._updateLocale(); }); const year = visibleDate.derive((d) => d.year().toFixed(0)); const month = visibleDate.derive((d) => d.monthString()); const firstDay = visibleDate.derive((d) => { return d.clone().startOfMonth(); }); const lastDay = visibleDate.derive((d) => { return d.clone().endOfMonth(); }); const monday = visibleDate.get().clone().minus({ days: visibleDate.get().dayOfWeek() - 1 }); const html = /* @__PURE__ */ jsxs("div", { class: "adw-calendar", role: "application", "aria-label": "Calendar", children: [ /* @__PURE__ */ jsx( Btn, { flat: true, onclick: api.method._showYearSelection, class: { "year-selector": true, hidden: sig.eq(api.context.selectMode, "year") }, "aria-label": sig.literal`Current year: ${year}. Click to select a different year.`, "aria-hidden": strBool(sig.eq(api.context.selectMode, "year")), children: year } ), /* @__PURE__ */ jsxs( "div", { class: { "month-selector": true, hidden: api.context.selectMode.derive( (m) => m === "month" || m === "year" ) }, role: "toolbar", "aria-label": "Month Navigation", "aria-hidden": strBool(api.context.selectMode.derive( (m) => m === "month" || m === "year" )), children: [ /* @__PURE__ */ jsx( Btn, { flat: true, onclick: api.method._handlePrevMonthPress, "aria-label": "Previous Month", title: "Previous Month", children: "\u25C2" } ), /* @__PURE__ */ jsx( Btn, { flat: true, class: "month-btn", onclick: api.method._showMonthSelection, "aria-label": sig.literal`Current month: ${month}. Click to select a different month.`, children: month } ), /* @__PURE__ */ jsx( Btn, { flat: true, onclick: api.method._handleNextMonthPress, "aria-label": "Next Month", title: "Next Month", children: "\u25B8" } ) ] } ), /* @__PURE__ */ jsxs( "div", { class: { "days-grid": true, visible: sig.eq(api.context.selectMode, "day") }, role: "grid", "aria-hidden": strBool(sig.not(sig.eq(api.context.selectMode, "day"))), children: [ Array.from({ length: 7 }, (_, idx) => { const d = monday.clone().plus({ days: idx }); return /* @__PURE__ */ jsx( "span", { class: [Typography.text, "header-day"], role: "columnheader", "aria-label": d.dayOfWeekString("long"), children: d.dayOfWeekString("narrow") } ); }), firstDay.derive((f) => { const weekDay = f.dayOfWeek(); return /* @__PURE__ */ jsx("div", { style: { display: "contents" }, children: Array.from( { length: weekDay - 1 }, (_, idx) => { const d = f.clone(); d.minus({ days: weekDay - idx - 1 }); const selected = selectedDate.derive((s) => s.isSameDate(d)); return /* @__PURE__ */ jsx( Btn, { flat: true, shape: "circular", class: { "prev-month-day": true, selected }, onclick: () => api.method._handleDateSelect(d), title: d.localeString(), "aria-label": d.localeString(), "aria-selected": strBool(selected), children: d.dayOfMonth("padded") } ); } ) }); }), visibleDate.derive((date) => { return Array.from( { length: date.countDaysOfThisMonth() }, (_, idx) => { const d = visibleDate.get().clone(); d.setDay(idx + 1); const selected = selectedDate.derive( (s) => s.isSameDate(d) ); return /* @__PURE__ */ jsx( Btn, { flat: true, shape: "circular", class: { "curr-month-day": true, selected }, onclick: () => api.method._handleDateSelect(d), title: d.localeString(), "aria-label": d.localeString(), "aria-selected": strBool(selected), children: d.dayOfMonth("padded") } ); } ); }), lastDay.derive((l) => { const weekDay = l.dayOfWeek(); if (weekDay == 7) { return /* @__PURE__ */ jsx(Fragment, {}); } return /* @__PURE__ */ jsx("div", { style: { display: "contents" }, role: "row", children: Array.from( { length: 7 - weekDay }, (_, idx) => { const d = l.clone(); d.plus({ days: idx + 1 }); const selected = selectedDate.derive((s) => s.isSameDate(d)); return /* @__PURE__ */ jsx( Btn, { flat: true, shape: "circular", class: { "next-month-day": true, selected }, onclick: () => api.method._handleDateSelect(d), title: d.localeString(), "aria-label": d.localeString(), "aria-selected": strBool(selected), children: d.dayOfMonth("padded") } ); } ) }); }) ] } ), /* @__PURE__ */ jsx( "div", { class: { "months-grid": true, visible: sig.eq(api.context.selectMode, "month") }, role: "grid", "aria-label": "Month selection", "aria-hidden": strBool( sig.not(sig.eq(api.context.selectMode, "month")) ), children: api.attribute.locale.signal.derive((locale) => { return Array.from({ length: 12 }, (_, idx) => { const d = new Dt(void 0, locale).setMonth(idx + 1); const selected = selectedDate.derive( (s) => s.month() == d.month() ); return /* @__PURE__ */ jsx( Btn, { class: { selected }, onclick: (e) => api.method._handleMonthSelect(e, d.month()), "aria-label": d.monthString(), "aria-selected": strBool(selected), children: d.monthString() } ); }); }) } ), /* @__PURE__ */ jsxs( "div", { class: { "years-controls": true, visible: sig.eq(api.context.selectMode, "year") }, role: "toolbar", "aria-label": "Year navigation", "aria-hidden": strBool(sig.not(sig.eq(api.context.selectMode, "year"))), children: [ /* @__PURE__ */ jsx( Btn, { flat: true, onclick: api.method.prevYearPage, "aria-label": "Previous 16 years", children: "\u25C2" } ), /* @__PURE__ */ jsx( Btn, { flat: true, onclick: api.method.nextYearPage, "aria-label": "Next 16 years", children: "\u25B8" } ) ] } ), /* @__PURE__ */ jsx( "div", { class: { "years-grid": true, visible: sig.eq(api.context.selectMode, "year") }, role: "grid", "aria-label": "Year selection", "aria-hidden": strBool(sig.not(sig.eq(api.context.selectMode, "year"))), children: api.context.yearsPage.derive((p) => { const pageStart = visibleDate.get().year() - 8 + p * 16; return Array.from({ length: 16 }, (_, idx) => { const year2 = pageStart + idx; const selected = selectedDate.derive((s) => s.year() == year2); return /* @__PURE__ */ jsx( Btn, { class: { selected }, onclick: (e) => api.method._handleYearSelect(e, year2), "aria-label": String(year2), "aria-selected": strBool(selected), children: String(year2) } ); }); }) } ), /* @__PURE__ */ jsx( "input", { hidden: true, type: "date", name: api.attribute.name.signal, "attribute:form": api.attribute.form.signal, "attribute:value": api.context.selectedDate.derive((d) => d.isoDate()), "aria-hidden": "true" } ) ] }); api.replace(html); }).register(); var AdwCalendar = CustomElement; export { AdwCalendar };