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.

502 lines (501 loc) 13.9 kB
import { Div as i, Img as j, Span as P, Button as I, OnState as W } from "@base-framework/atoms"; import { Component as N, Data as Y, Atom as z, DateTime as B } from "@base-framework/base"; import { B as p } from "./buttons-Cm9etaEG.js"; import { Icons as S } from "./icons.es.js"; const H = (e, t) => { const n = e ? e.getBoundingClientRect() : { top: 0, bottom: 0, left: 0 }, s = t.getBoundingClientRect(), r = 10, a = globalThis.scrollX, l = globalThis.scrollY; let c = n.left + a, g = n.bottom + l; const d = globalThis.innerHeight - n.bottom, h = n.top; return c + s.width > globalThis.innerWidth && (c = globalThis.innerWidth - s.width - r), d < s.height && h > d ? g = n.top + l - s.height - r : d < s.height && (g = n.bottom + l - (s.height - d) - r), { x: c, y: g }; }; class ht extends N { /** * This will set up the data. * * @returns {object} */ setData() { const t = this.parent.data || new Y(); 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 i({ 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: s }) => n.newState === "closed" ? s.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: (s) => { this.state.open === !1 && this.destroy(); } } }; } /** * Updates the dropdown position. * * @returns {void} */ updatePosition() { const t = this.button ?? null, n = this.panel, s = H(t, n); this.data.position = s; } /** * 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 R = z(({ src: e, alt: t }) => e ? j({ 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" }) : null), X = (e) => e && (Array.isArray(e) && (e = e.join(" ")), typeof e != "string" && (e = String(e)), e.split(" ").map((t) => t.charAt(0)).join("").toUpperCase()), O = (e) => !e || e.length < 2 ? e : X(e), E = (e) => P([e, (t, n) => { n.textContent = O(t); }]), T = { 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" }, k = { 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" }, G = (e) => T[e] || T.default, L = (e) => k[e] || k.default, U = (e, t = null, n = "md") => { const s = O(e), r = L(n); return i( { class: ` flex items-center justify-center w-full h-full rounded-full bg-muted text-muted-foreground font-medium ${r} ` }, [ t ? E(t) : P({ class: "uppercase" }, s) ] ); }, dt = z(({ src: e, alt: t, fallbackText: n, watcherFallback: s, size: r }) => { const a = G(r); return i( { class: `relative flex items-center justify-center ${a}` }, [ R({ src: e, alt: t }), U(n, s, r) ] ); }), _ = ({ currentYear: e, onSelect: t }) => i( { class: "grid grid-cols-3 gap-2" }, B.monthNames.map( (n, s) => p( { click: () => t(s), variant: "ghost", "aria-label": `Select ${n} ${e}` }, n.substring(0, 3) ) ) ), D = (e) => (e *= 1, e < 10 ? `0${e}` : String(e)), q = (e) => (e.indexOf("T") === -1 && e.indexOf(" ") === -1 && (e += "T00:00:01"), e.replace(" ", "T"), e), x = (e, t, n) => `${e}-${D(t + 1)}-${D(n)}`, J = (e) => e ? "bg-accent text-primary" : "", K = (e) => e ? "text-muted-foreground opacity-50" : "", Q = (e, t) => e === t, V = (e, t) => Q(e, t) ? "bg-primary text-primary-foreground" : "", Z = (e, t, n, s) => { const r = V(t, s); return r || (e ? J(e) : n ? K(n) : "text-foreground"); }, C = (e) => { const { day: t, currentDate: n, date: s, isToday: r, isOutsideMonth: a, select: l, disabled: c } = e; return I( { class: ` flex items-center justify-center h-9 w-auto p-0 font-normal text-sm rounded-md ${Z(r, n, a, s)} hover:bg-muted/50 hover:text-muted-foreground focus:z-10 disabled:pointer-events-none disabled:opacity-50 `, disabled: c || t === null, "aria-label": t ? `Day ${t}` : null, // Only call select if it's not disabled. click: () => !c && l(s) }, t.toString() ); }, M = (e, t, n, s) => e === s.date && t === s.month && n === s.year, tt = (e, t, n, s = !1) => { const { year: r, month: a } = e, l = x(r, a, e.date), c = new Date(r, a, 1).getDay(), g = new Date(r, a + 1, 0).getDate(), d = new Date(r, a, 0).getDate(), h = [], y = a === 0 ? 11 : a - 1, w = a === 0 ? r - 1 : r; for (let o = c - 1; o >= 0; o--) { const u = d - o, f = M(u, y, w, t), m = new Date(w, y, u) < new Date(t.year, t.month, t.date), F = s && m; h.push( C({ day: u, currentDate: l, date: x(w, y, u), isToday: f, isOutsideMonth: !0, select: n, disabled: F }) ); } for (let o = 1; o <= g; o++) { const u = M(o, a, r, t), f = new Date(r, a, o) < new Date(t.year, t.month, t.date), m = s && f; h.push( C({ day: o, currentDate: l, date: x(r, a, o), isToday: u, isOutsideMonth: !1, select: n, disabled: m }) ); } const v = a === 11 ? 0 : a + 1, b = a === 11 ? r + 1 : r, A = (7 - h.length % 7) % 7; for (let o = 1; o <= A; o++) { const u = M(o, v, b, t), f = new Date(b, v, o) < new Date(t.year, t.month, t.date), m = s && f; h.push( C({ day: o, currentDate: l, date: x(b, v, o), isToday: u, isOutsideMonth: !0, select: n, disabled: m }) ); } return h; }, $ = ({ label: e, click: t }) => p( { 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" ? S.chevron.single.left : S.chevron.single.right } ), et = ({ onMonthClick: e, onYearClick: t, next: n, previous: s }) => i({ class: "flex items-center justify-center space-x-2 relative min-h-12 text-sm font-medium" }, [ p({ click: e, variant: "ghost", "aria-label": "Select month" }, "[[monthName]]"), p({ click: t, variant: "ghost", "aria-label": "Select year" }, "[[current.year]]"), $({ label: "Previous", click: s }), $({ label: "Next", click: n }) ]), nt = (e) => i( { class: "flex items-center justify-center h-9 w-auto text-[0.8rem] font-normal text-muted-foreground" }, e ), st = () => ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map(nt), rt = (e) => i({ class: "rdp w-full space-y-1" }, [ et({ onMonthClick: e.onMonthClick, onYearClick: e.onYearClick, next: e.next, previous: e.previous }), i({ class: "flex flex-auto flex-col w-full", onSet: [ "currentDate", () => [ i({ class: "grid grid-cols-7" }, st()), i( { class: "grid grid-cols-7" }, tt( e.current, e.today, e.select, e.blockPriorDates ) ) ] ] }) ]), at = ({ currentMonth: e, currentYear: t, onSelect: n }) => { const s = t - 50, r = Array.from({ length: 101 }, (a, l) => s + l); return i( { class: "grid grid-cols-4 gap-2 overflow-y-auto max-h-72" }, r.map( (a) => p( { click: () => n(a), variant: "ghost", "aria-label": `Select ${a}` }, a.toString() ) ) ); }; class gt extends N { /** * 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(q(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), s = n.getMonth(); return new Y({ monthName: this.getMonthName(s), currentDate: `${n.getFullYear()}-${s + 1}-${n.getDate()}`, current: { date: n.getDate(), year: n.getFullYear(), month: s }, 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 B.monthNames[t]; } /** * This will go to the previous month. * * @returns {void} */ goToPreviousMonth() { const t = this.data; let n = t.current.month, s = t.current.year; n === 0 ? (n = 11, s--) : n--, this.setCurrentDate(n, s); } /** * This will go to the next month. * * @returns {void} */ goToNextMonth() { const t = this.data; let n = t.current.month, s = t.current.year; n === 11 ? (n = 0, s++) : n++, this.setCurrentDate(n, s); } /** * This will set the current month and year. * * @param {number} month * @param {number} year * @param {number} [date=null] * @returns {void} */ setCurrentDate(t, n, s = null) { const r = this.data; r.current.month = t, r.current.year = n, typeof s == "number" && (r.current.date = D(s)), r.currentDate = `${n}-${D(t + 1)}-${r.current.date}`, r.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 i({ class: "calendar-container p-3 rounded-md border min-w-80" }, [ W("view", (t) => { switch (t) { case "months": return _( { currentYear: this.data.current.year, onSelect: (n) => { this.setCurrentDate(n, this.data.current.year), this.state.view = "calendar"; } } ); case "years": return at( { 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 rt({ current: this.data.current, today: this.data.today, select: (n) => this.selectDate(n), next: () => this.goToNextMonth(), previous: () => this.goToPreviousMonth(), blockPriorDates: this.blockPriorDates || !1, onMonthClick: () => this.state.view = "months", onYearClick: () => this.state.view = "years" }); } }) ]); } } export { dt as A, tt as C, C as D, x as F, rt as M, ht as P, nt as a, gt as b, q as c, H as g, D as p };