UNPKG

@base-framework/ui

Version:

This is a UI package that adds components and atoms that use Tailwind CSS and a theme based on Shadcn.

834 lines (833 loc) 25.2 kB
import { Div as h, Img as _, Span as H, Button as L, OnState as J, On as z } from "@base-framework/atoms"; import { Component as Y, Data as B, Atom as j, DateTime as T } from "@base-framework/base"; import { B as m } from "./buttons-CHEs54Wl.js"; import { Icons as P } from "./icons.es.js"; const U = (e, t) => { const n = e ? e.getBoundingClientRect() : { top: 0, bottom: 0, left: 0 }, a = t.getBoundingClientRect(), s = 10, r = globalThis.scrollX, l = globalThis.scrollY; let i = n.left + r, d = n.bottom + l; const g = globalThis.innerHeight - n.bottom, f = n.top; return i + a.width > globalThis.innerWidth && (i = globalThis.innerWidth - a.width - s), g < a.height && f > g ? d = n.top + l - a.height - s : g < a.height && (d = n.bottom + l - (a.height - g) - s), { x: i, y: d }; }; class Pt extends Y { /** * This will set up the data. * * @returns {object} */ setData() { const t = this.parent.data || new B(); return t.set({ position: { x: 0, y: 0 } }), t; } /** * This will get the class size. * * @returns {string} */ getSize() { switch (this.size || "lg") { // @ts-ignore case "sm": return "w-48"; // @ts-ignore case "md": return "w-64"; case "lg": return "w-[250px]"; // @ts-ignore case "xl": return "w-96"; // @ts-ignore case "2xl": return "w-[400px]"; // @ts-ignore case "fit": return "w-fit"; // @ts-ignore case "full": return "w-full"; } } /** * This will render the modal component. * * @returns {object} */ render() { const t = this.getSize(); return h({ class: `absolute inset-auto fadeIn mt-2 rounded-md p-0 shadow-lg bg-popover min-h-12 backdrop:bg-transparent text-inherit r z-30 ${t}`, popover: "manual", toggle: (n, { state: a }) => n.newState === "closed" ? a.open = !1 : null, style: "top: [[position.y]]px; left: [[position.x]]px" }, this.children); } /** * This will setup the states. * * @returns {object} */ setupStates() { return { open: { id: this.parent.getId(), callBack: (a) => { this.state.open === !1 && this.destroy(); } } }; } /** * Updates the dropdown position. * * @returns {void} */ updatePosition() { const t = this.button ?? null, n = this.panel, a = U(t, n); this.data.position = a; } /** * This will run after the setup. * * @returns {void} */ afterSetup() { this.panel.showPopover(), this.updatePosition(); } /** * This will check if the element clicked was in the * component of the button. * * @param {object} element * @returns {boolean} */ isOutsideClick(t) { return !this.panel.contains(t) && this.button && !this.button.contains(t); } /** * This will set up the events. * * @returns {array} */ setupEvents() { return [ ["click", document, (t) => { this.isOutsideClick(t.target) && (this.state.open = !1); }], ["resize", globalThis, (t) => this.updatePosition()], ["scroll", document, (t) => this.updatePosition()] ]; } /** * This will override the set up to use the app shell. * * @param {object} container */ setContainer(t) { this.container = app.root; } /** * This will hide the popover before destroying. * * @returns {void} */ beforeDestroy() { this.panel.hidePopover(); } } const q = j(({ src: e, alt: t }) => !e || e.indexOf(".") === -1 && e.indexOf("[[") === -1 ? null : _({ class: "absolute w-full h-full rounded-full object-cover fadeIn", src: e, alt: t, /** * If there's an error loading the image, hide it. */ error: (n) => n.target.style.display = "none" })), K = (e) => e && (Array.isArray(e) && (e = e.join(" ")), typeof e != "string" && (e = String(e)), e.split(" ").map((t) => t.charAt(0)).join("").toUpperCase()), G = (e) => !e || e.length < 2 ? e : K(e), Q = (e) => H([e, (t, n) => { n.textContent = G(t); }]), A = { xs: "h-6 w-6", sm: "h-8 w-8", md: "h-12 w-12", lg: "h-16 w-16", xl: "h-24 w-24", "2xl": "h-32 w-32", "3xl": "h-48 w-48", "4xl": "h-64 w-64", default: "h-12 w-12" }, I = { xs: "text-[7px]", sm: "text-xs", md: "text-base", lg: "text-xl", xl: "text-2xl", "2xl": "text-3xl", "3xl": "text-4xl", "4xl": "text-5xl", default: "text-base" }, V = (e) => A[e] || A.default, Z = (e) => I[e] || I.default, tt = (e, t = null, n = "md") => { const a = G(e), s = Z(n); return h( { class: ` flex items-center justify-center w-full h-full rounded-full bg-muted text-muted-foreground font-medium ${s} ` }, [ t ? Q(t) : H({ class: "uppercase" }, a) ] ); }, Tt = j(({ src: e, alt: t, fallbackText: n, watcherFallback: a, size: s }) => { const r = V(s); return h( { class: `relative flex items-center justify-center ${r}` }, [ q({ src: e, alt: t }), tt(n, a, s) ] ); }), et = ({ currentMonth: e, currentYear: t, onSelect: n }) => h( { class: "grid grid-cols-3 gap-2" }, T.monthNames.map( (a, s) => m( { click: (r) => { r.preventDefault(), r.stopPropagation(), n(s); }, variant: e === s ? "primary" : "ghost", "aria-label": `Select ${a} ${t}` }, a.substring(0, 3) ) ) ), D = (e) => (e *= 1, e < 10 ? `0${e}` : String(e)), nt = (e) => (e.indexOf("T") === -1 && e.indexOf(" ") === -1 && (e += "T00:00:01"), e.replace(" ", "T"), e), w = (e, t, n) => `${e}-${D(t + 1)}-${D(n)}`, at = (e) => e ? "bg-accent text-primary" : "", st = (e) => e ? "text-muted-foreground opacity-50" : "", rt = (e, t) => e === t, ot = (e, t) => rt(e, t) ? "bg-primary text-primary-foreground" : "", it = (e, t, n, a) => { const s = ot(t, a); return s || (e ? at(e) : n ? st(n) : "text-foreground"); }, N = (e) => { const { day: t, currentDate: n, date: a, isToday: s, isOutsideMonth: r, select: l, disabled: i } = e; return L( { class: ` flex items-center justify-center h-9 w-auto p-0 font-normal text-sm rounded-md ${it(s, n, r, a)} hover:bg-muted/50 hover:text-muted-foreground focus:z-10 disabled:pointer-events-none disabled:opacity-50 `, disabled: i || t === null, "aria-label": t ? `Day ${t}` : null, // Only call select if it's not disabled. click: () => !i && l(a) }, t.toString() ); }, O = (e, t, n, a) => e === a.date && t === a.month && n === a.year, lt = (e, t, n, a = !1) => { const { year: s, month: r } = e, l = w(s, r, e.date), i = new Date(s, r, 1).getDay(), d = new Date(s, r + 1, 0).getDate(), g = new Date(s, r, 0).getDate(), f = [], C = r === 0 ? 11 : r - 1, v = r === 0 ? s - 1 : s; for (let o = i - 1; o >= 0; o--) { const u = g - o, p = O(u, C, v, t), y = new Date(v, C, u) < new Date(t.year, t.month, t.date), x = a && y; f.push( N({ day: u, currentDate: l, date: w(v, C, u), isToday: p, isOutsideMonth: !0, select: n, disabled: x }) ); } for (let o = 1; o <= d; o++) { const u = O(o, r, s, t), p = new Date(s, r, o) < new Date(t.year, t.month, t.date), y = a && p; f.push( N({ day: o, currentDate: l, date: w(s, r, o), isToday: u, isOutsideMonth: !1, select: n, disabled: y }) ); } const b = r === 11 ? 0 : r + 1, $ = r === 11 ? s + 1 : s, c = (7 - f.length % 7) % 7; for (let o = 1; o <= c; o++) { const u = O(o, b, $, t), p = new Date($, b, o) < new Date(t.year, t.month, t.date), y = a && p; f.push( N({ day: o, currentDate: l, date: w($, b, o), isToday: u, isOutsideMonth: !0, select: n, disabled: y }) ); } return f; }, R = ({ label: e, click: t }) => m( { class: ` inline-flex items-center justify-center h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 text-muted-foreground absolute ${e === "Previous" ? "left-1" : "right-1"} focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 `, click: t, "aria-label": `${e} month`, variant: "icon", icon: e === "Previous" ? P.chevron.single.left : P.chevron.single.right } ), ct = ({ onMonthClick: e, onYearClick: t, next: n, previous: a }) => h({ class: "flex items-center justify-center gap-x-2 relative min-h-12 text-sm font-medium" }, [ m({ click: e, variant: "ghost", "aria-label": "Select month" }, "[[monthName]]"), m({ click: t, variant: "ghost", "aria-label": "Select year" }, "[[current.year]]"), R({ label: "Previous", click: a }), R({ label: "Next", click: n }) ]), ht = (e) => h( { class: "flex items-center justify-center h-9 w-auto text-[0.8rem] font-normal text-muted-foreground" }, e ), ut = () => ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map(ht), dt = (e) => h({ class: "rdp flex flex-auto flex-col w-full gap-y-1" }, [ ct({ onMonthClick: e.onMonthClick, onYearClick: e.onYearClick, next: e.next, previous: e.previous }), h({ class: "flex flex-auto flex-col w-full", onSet: [ "currentDate", () => [ h({ class: "grid grid-cols-7" }, ut()), h( { class: "grid grid-cols-7" }, lt( e.current, e.today, e.select, e.blockPriorDates ) ) ] ] }) ]), gt = ({ currentMonth: e, currentYear: t, onSelect: n }) => { const a = t - 50, s = Array.from({ length: 101 }, (r, l) => a + l); return h( { class: "grid grid-cols-4 gap-2 overflow-y-auto max-h-72" }, s.map( (r) => m( { click: (l) => { l.preventDefault(), l.stopPropagation(), n(r); }, variant: r === t ? "primary" : "ghost", "aria-label": `Select ${r}` }, r.toString() ) ) ); }; class Nt extends Y { /** * This will declare the props for the compiler. * * @returns {void} */ declareProps() { this.selectedDate = null, this.selectedCallBack = null, this.blockPriorDates = !1; } /** * This will get the selected data. * * @param {object} today * @returns {Date} */ getSelectedDate(t) { const n = this.selectedDate ? new Date(nt(this.selectedDate)) : t; return new Date(n.getFullYear(), n.getMonth(), n.getDate()); } /** * This will set up the data for the calendar. * * @returns {Data} */ setData() { const t = /* @__PURE__ */ new Date(), n = this.getSelectedDate(t), a = n.getMonth(); return new B({ monthName: this.getMonthName(a), currentDate: `${n.getFullYear()}-${a + 1}-${n.getDate()}`, current: { date: n.getDate(), year: n.getFullYear(), month: a }, today: { date: t.getDate(), month: t.getMonth(), year: t.getFullYear() } }); } /** * This will set up the states for the calendar. * * @return {object} */ setupStates() { return { view: "calendar" // 'calendar' | 'months' | 'years' }; } /** * This will get the name of the month. * * @param {number} month * @returns {string} */ getMonthName(t) { return T.monthNames[t]; } /** * This will go to the previous month. * * @returns {void} */ goToPreviousMonth() { const t = this.data; let n = t.current.month, a = t.current.year; n === 0 ? (n = 11, a--) : n--, this.setCurrentDate(n, a); } /** * This will go to the next month. * * @returns {void} */ goToNextMonth() { const t = this.data; let n = t.current.month, a = t.current.year; n === 11 ? (n = 0, a++) : n++, this.setCurrentDate(n, a); } /** * This will set the current month and year. * * @param {number} month * @param {number} year * @param {number} [date=null] * @returns {void} */ setCurrentDate(t, n, a = null) { const s = this.data; s.current.month = t, s.current.year = n, typeof a == "number" && (s.current.date = D(a)), s.currentDate = `${n}-${D(t + 1)}-${s.current.date}`, s.monthName = this.getMonthName(t); } /** * This will select a date. * * @param {string} date * @returns {void} */ selectDate(t) { const n = /* @__PURE__ */ new Date(t + "T00:00:00"); this.setCurrentDate(n.getMonth(), n.getFullYear(), n.getDate()), typeof this.selectedCallBack == "function" && this.selectedCallBack(this.data.currentDate); } /** * This will render the calendar. * * @returns {object} */ render() { return h({ class: "calendar-container p-3 rounded-md border min-w-80" }, [ J("view", (t) => { switch (t) { case "months": return et( { currentMonth: this.data.current.month, currentYear: this.data.current.year, onSelect: (n) => { this.setCurrentDate(n, this.data.current.year), this.state.view = "calendar"; } } ); case "years": return gt( { currentMonth: this.data.current.month, currentYear: this.data.current.year, onSelect: (n) => { this.setCurrentDate(this.data.current.month, n), this.state.view = "calendar"; } } ); default: return dt({ current: this.data.current, today: this.data.today, select: (n) => this.selectDate(n), next: () => this.goToNextMonth(), previous: () => this.goToPreviousMonth(), blockPriorDates: this.blockPriorDates || !1, onMonthClick: (n) => { n.preventDefault(), n.stopPropagation(), this.state.view = "months"; }, onYearClick: (n) => { n.preventDefault(), n.stopPropagation(), this.state.view = "years"; } }); } }) ]); } } const W = ({ label: e, click: t }) => m( { class: ` inline-flex items-center justify-center h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 text-muted-foreground absolute ${e === "Previous" ? "left-1" : "right-1"} focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 `, click: t, "aria-label": `${e} month`, variant: "icon", icon: e === "Previous" ? P.chevron.single.left : P.chevron.single.right } ), ft = ({ onMonthClick: e, onYearClick: t, next: n, previous: a }) => h({ class: "flex items-center justify-center gap-x-2 relative min-h-12 text-sm font-medium" }, [ m({ click: e, variant: "ghost", "aria-label": "Select month" }, "[[monthName]]"), m({ click: t, variant: "ghost", "aria-label": "Select year" }, "[[current.year]]"), W({ label: "Previous", click: a }), W({ label: "Next", click: n }) ]), mt = (e) => h({ class: "h-9 flex items-center justify-center font-medium" }, e), pt = () => h( { class: "grid grid-cols-7 gap-1 text-center text-xs font-medium text-muted-foreground mb-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map(mt) ), yt = ({ day: e, iso: t, disabled: n, isStart: a, isEnd: s, isBetween: r, isOtherMonth: l, click: i }) => { let d = "ghost", g = ""; return a || s ? (d = "default", g = "bg-primary text-primary-foreground hover:bg-primary/90") : r && (g = "bg-accent text-accent-foreground hover:bg-accent/80"), n && (g += " opacity-50 cursor-not-allowed"), l && (g += " text-muted-foreground opacity-50"), m( { class: `flex items-center justify-center p-0 text-sm font-medium rounded-md transition-colors ${g}`, variant: d, disabled: n, click: (f) => { f.preventDefault(), f.stopPropagation(), n || i(); } }, e.toString() ); }, Dt = ({ today: e, current: t, blockPriorDates: n, onDateClick: a }) => { const { start: s, end: r } = t, l = new Date(t.year, t.month, 1).getDay(), i = new Date(t.year, t.month + 1, 0).getDate(), d = [], g = t.month === 0 ? 11 : t.month - 1, f = t.month === 0 ? t.year - 1 : t.year, C = new Date(f, g + 1, 0).getDate(), v = t.month === 11 ? 0 : t.month + 1, b = t.month === 11 ? t.year + 1 : t.year; for (let c = l - 1; c >= 0; c--) { const o = C - c, u = w(f, g, o), p = new Date(f, g, o), y = new Date(e.year, e.month, e.date), x = p < y, M = n && x, S = s === u, k = r === u, X = s && r && u > s && u < r; d.push({ day: o, iso: u, disabled: M, isStart: S, isEnd: k, isBetween: X, isOtherMonth: !0, click: () => a(u) }); } for (let c = 1; c <= i; c++) { const o = w(t.year, t.month, c), u = new Date(t.year, t.month, c), p = new Date(e.year, e.month, e.date), y = u < p, x = n && y, M = s === o, S = r === o, k = s && r && o > s && o < r; d.push({ day: c, iso: o, disabled: x, isStart: M, isEnd: S, isBetween: k, isOtherMonth: !1, click: () => { a(o); } }); } const F = (7 - d.length % 7) % 7; for (let c = 1; c <= F; c++) { const o = w(b, v, c), u = new Date(b, v, c), p = new Date(e.year, e.month, e.date), y = u < p, x = n && y, M = s === o, S = r === o, k = s && r && o > s && o < r; d.push({ day: c, iso: o, disabled: x, isStart: M, isEnd: S, isBetween: k, isOtherMonth: !0, click: () => a(o) }); } return h( { class: "grid grid-cols-7 gap-1" }, d.map( (c, o) => yt({ day: c.day, iso: c.iso, disabled: c.disabled, isStart: c.isStart, isEnd: c.isEnd, isBetween: c.isBetween, isOtherMonth: c.isOtherMonth, click: c.click }) ) ); }, xt = j((e, t) => h({ class: "flex flex-auto flex-col" }, [ ft({ onMonthClick: e.onMonthClick, onYearClick: e.onYearClick, next: e.next, previous: e.previous }), h({ class: "flex flex-auto flex-col w-full", onSet: [ "currentDate", () => [ pt(), Dt({ today: e.today, current: e.current, blockPriorDates: e.blockPriorDates, onDateClick: e.onDateClick }) ] ] }) ])), wt = ({ currentMonth: e, currentYear: t, onSelect: n }) => h( { class: "grid grid-cols-3 gap-2" }, T.monthNames.map( (a, s) => m( { click: (r) => { r.preventDefault(), r.stopPropagation(), n(s); }, variant: e === s ? "primary" : "ghost", "aria-label": `Select ${a} ${t}` }, a.substring(0, 3) ) ) ), vt = ({ start: e, end: t, selecting: n, onSelectStart: a, onSelectEnd: s }) => h({ class: "flex gap-x-2 mb-4" }, [ z("selecting", (r) => m({ click: a, variant: r === "start" ? "primary" : "outline", class: "flex-1" }, [ h({ class: "font-medium" }, E("current.start", "Start Date")) ])), z("selecting", (r) => m({ click: s, variant: r === "end" ? "primary" : "outline", class: "flex-1" }, [ h({ class: "font-medium" }, E("current.end", "End Date")) ])) ]), E = (e, t) => [`[[${e}]]`, (n) => n == null ? t : bt(n)], bt = (e) => { const t = /* @__PURE__ */ new Date(e + "T00:00:00"), n = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], a = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; return `${n[t.getDay()]}, ${t.getDate()} ${a[t.getMonth()]}`; }, Ct = ({ currentYear: e, onSelect: t }) => { const n = e - 50, a = Array.from({ length: 101 }, (s, r) => n + r); return h( { class: "grid grid-cols-4 gap-2 overflow-y-auto max-h-72" }, a.map( (s) => m( { click: (r) => { r.preventDefault(), r.stopPropagation(), t(s); }, variant: s === e ? "primary" : "ghost", "aria-label": `Select ${s}` }, s.toString() ) ) ); }; class Ot extends Y { /** * Declare compiler props. * * @returns {void} */ declareProps() { this.startDate = null, this.endDate = null, this.onRangeSelect = null, this.blockPriorDates = !1; } /** * Initialize reactive data for today and current view. * * @returns {Data} */ setData() { const t = /* @__PURE__ */ new Date(), n = this.startDate ? /* @__PURE__ */ new Date(this.startDate + "T00:00:00") : t, a = n.getMonth(), s = n.getFullYear(); return new B({ today: { date: t.getDate(), month: t.getMonth(), year: t.getFullYear() }, monthName: this.getMonthName(a), currentData: `${n.getFullYear()}-${D(n.getMonth() + 1)}-${D(n.getDate())}`, current: { date: t.getDate(), month: a, year: s, start: this.startDate, end: this.endDate }, selecting: "start" }); } /** * This will get the name of the month. * * @param {number} month * @returns {string} */ getMonthName(t) { return T.monthNames[t]; } /** * Initialize component state. * * @returns {{view:string}} */ setupStates() { return { view: "calendar" // 'calendar', 'months', or 'years' }; } /** * Handle a date cell click. * * @param {string} isoDate * @returns {void} */ handleClick(t) { if (this.data.selecting === "start") { this.data.current.start = t, this.data.current.end = null, this.data.selecting = "end"; const n = /* @__PURE__ */ new Date(t + "T00:00:00"); this.setCurrent({ month: n.getMonth(), year: n.getFullYear(), date: n.getDate() }); } else { this.data.current.start && t < this.data.current.start ? (this.data.current.end = this.data.current.start, this.data.current.start = t) : this.data.current.end = t, this.data.selecting = "start"; const n = /* @__PURE__ */ new Date(t + "T00:00:00"); this.setCurrent({ month: n.getMonth(), year: n.getFullYear(), date: n.getDate() }), typeof this.onRangeSelect == "function" && this.onRangeSelect(this.data.current.start, this.data.current.end); } } /** * Update current month/year in data. * * @param {object} obj * @returns {void} */ setCurrent({ month: t, year: n, date: a = null }) { const s = this.data.current; s.month = (t + 12) % 12, s.year = n + (t < 0 ? -1 : t > 11 ? 1 : 0), a !== null && (s.date = a), this.data.monthName = this.getMonthName(s.month), this.data.currentDate = `${n}-${D(t + 1)}-${D(s.date)}`; } /** * Render the range calendar. * * @returns {object} */ render() { const { today: t, current: n, selecting: a } = this.data, { start: s, end: r } = n; return h({ class: "range-calendar border border-border rounded-lg shadow-md p-4 w-full max-w-sm min-w-80" }, [ vt({ start: s, end: r, selecting: a, onSelectStart: (l) => { l.preventDefault(), l.stopPropagation(), this.data.selecting = "start"; }, onSelectEnd: (l) => { l.preventDefault(), l.stopPropagation(), this.data.selecting = "end"; } }), J("view", (l) => { switch (l) { case "months": return wt( { currentMonth: n.month, currentYear: n.year, onSelect: (i) => { this.setCurrent({ month: i, year: n.year }), this.state.view = "calendar"; } } ); case "years": return Ct( { currentYear: n.year, onSelect: (i) => { this.setCurrent({ month: n.month, year: i }), this.state.view = "calendar"; } } ); default: return xt({ monthName: this.data.monthName, year: n.year, today: t, current: n, blockPriorDates: this.blockPriorDates, onDateClick: (i) => this.handleClick(i), onMonthClick: (i) => { i.preventDefault(), i.stopPropagation(), this.state.view = "months"; }, onYearClick: (i) => { i.preventDefault(), i.stopPropagation(), this.state.view = "years"; }, next: () => { const i = this.data.current, d = i.month === 11 ? { month: 0, year: i.year + 1 } : { month: i.month + 1, year: i.year }; this.setCurrent(d); }, previous: () => { const i = this.data.current, d = i.month === 0 ? { month: 11, year: i.year - 1 } : { month: i.month - 1, year: i.year }; this.setCurrent(d); } }); } }) ]); } } export { Tt as A, lt as C, N as D, w as F, dt as M, Pt as P, Ot as R, ht as a, Nt as b, nt as c, U as g, D as p };