@base-framework/ui
Version:
This is a UI package that adds components and atoms that use Tailwind CSS and a theme based on Shadcn.
1,451 lines (1,450 loc) • 40.2 kB
JavaScript
import { Div as n, H5 as _, P as b, I as g, Li as O, Span as a, Ul as V, Button as m, OnState as v, Label as W, Form as R, H2 as A, Header as B, Footer as M, A as Y, H3 as G, Checkbox as J, Nav as K, Input as C, UseParent as Q, Time as X, Dialog as Z } from "@base-framework/atoms";
import { Atom as c, Component as p, Html as L, Dom as ee, base as te, Data as k, Builder as U, Jot as S, DateTime as $ } from "@base-framework/base";
import { P as D, b as se } from "./calendar-BDqm833e.js";
import { B as h, I as x } from "./buttons-CVEwmPAi.js";
import { Icons as u } from "./icons.es.js";
import { a as w } from "./veil-D4dRxILB.js";
import { Timer as oe, List as ne, DynamicTime as re } from "@base-framework/organisms";
const P = {
info: {
borderColor: "border-blue-500",
bgColor: "bg-muted/10",
iconColor: "text-blue-500"
},
warning: {
bgColor: "bg-muted/10",
borderColor: "border-warning",
iconColor: "text-warning"
},
destructive: {
bgColor: "bg-muted/10",
borderColor: "border-destructive",
iconColor: "text-red-500"
},
success: {
bgColor: "bg-muted/10",
borderColor: "border-emerald-500",
iconColor: "text-emerald-500"
},
default: {
borderColor: "border",
bgColor: "bg-muted/10",
iconColor: "text-muted-foreground"
}
}, le = (e, t) => n({ class: `flex items-center justify-center h-6 w-6 mr-3 ${t}` }, [
g({ html: e })
]), ie = (e) => _({ class: "font-semibold" }, e), ae = (e) => b({ class: "text-sm text-muted-foreground" }, e), mt = c(({ title: e, description: t, icon: s, type: o = "default" }) => {
const { borderColor: r, bgColor: l, iconColor: i } = P[o] || P.default;
return n({ class: `flex items-start p-4 border rounded-lg ${l} ${r}` }, [
// Icon and content
s && le(s, i),
n({ class: "flex flex-col" }, [
ie(e),
ae(t)
])
]);
});
class ce extends p {
/**
* This will declare the props for the compiler.
*
* @returns {void}
*/
declareProps() {
this.removingClass = "";
}
/**
* This will remove the component from the DOM after a delay.
*
* @returns {void}
*/
remove() {
this.prepareDestroy(), this.removeContext();
const t = this.panel, s = this.removingClass;
if (!s) {
L.removeElement(t);
return;
}
ee.addClass(t, s), te.on("animationend", t, (o) => L.removeElement(t));
}
}
const de = (e) => a({ class: "ml-auto text-xs tracking-widest opacity-60" }, e), ue = (e) => a({ class: "flex w-4 h-4", html: e }), he = (e) => a({ class: "flex-auto" }, e), me = (e, t) => O({
class: "relative flex cursor-pointer hover:bg-muted/50 select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
click: () => t(e)
}, [
e.icon && ue(e.icon),
he(e.label),
e.shortcut && de(e.shortcut)
]), fe = (e, t) => V({ class: "grid gap-2" }, [
e.map((s) => me(s, t))
]), ge = (e) => n({ class: "w-full z-10" }, [
n({
class: "max-h-60 border rounded-md overflow-y-auto p-1 grid gap-2 divide-y divide-border",
for: ["groups", (t) => fe(t, e)]
})
]), be = ({ label: e, icon: t, toggleDropdown: s }) => m({
cache: "button",
class: `inline-flex items-center justify-between rounded-md border border-input
bg-background px-2 py-2 text-sm font-medium hover:bg-muted
focus:outline-none transition duration-150 ease-in-out`,
click: s
}, [
e && a(e),
t && g({ html: t })
]), pe = ({ onSelect: e }) => n([
v(
"open",
(t, s, o) => t ? new D({
cache: "dropdown",
parent: o,
button: o.button
}, [
ge(e)
]) : null
)
]);
class ft extends p {
/**
* This will declare the props for the compiler.
*
* @returns {void}
*/
declareProps() {
this.label = null, this.icon = null, this.onSelect = null, this.groups = [];
}
/**
* Initializes component data.
*
* @returns {Data}
*/
setData() {
return new k({
groups: this.groups || []
});
}
/**
* Initializes the component state.
*
* @returns {object}
*/
setupStates() {
return {
open: !1,
selectedItem: null
};
}
/**
* Toggles the dropdown open state.
*
* @returns {void}
*/
toggleDropdown() {
this.state.toggle("open");
}
/**
* Handles item selection within the dropdown.
*
* @param {object} item - The selected item object
* @returns {void}
*/
handleSelect(t) {
this.state.selectedItem = t, this.state.open = !1, typeof this.onSelect == "function" && this.onSelect(t);
}
/**
* Renders the Dropdown component.
*
* @returns {object}
*/
render() {
return n({ class: "relative" }, [
be({
label: this.label,
icon: this.icon,
toggleDropdown: this.toggleDropdown.bind(this)
}),
pe({ onSelect: this.handleSelect.bind(this) })
]);
}
}
const xe = c((e, t) => n({ ...e, class: "flex flex-auto flex-col space-y-2" }, t)), we = c((e, t) => W({ ...e, class: "flex auto text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" }, t)), ye = c((e, t) => b({ ...e, class: "text-sm text-muted-foreground italic" }, t)), ve = c((e, t) => b({ ...e, class: "text-sm text-destructive" }, t)), Ce = (e) => e.tag === "input" || e.tag === "select" || e.tag === "textarea", q = (e, t, s) => e.map((o) => (o.children && o.children.length > 0 && (o.children = q(o.children, t, s)), o.required && Ce(o) ? {
...o,
aria: {
invalid: ["hasError"]
},
invalid: s,
input: t
} : o)), ke = c((e, t) => {
const r = q(t, (l) => {
l.target.checkValidity() && e.setError(null);
}, (l) => {
e.setError(l.target.validationMessage);
});
return n({
...e,
class: "w-full"
}, r);
}), gt = w(
{
/**
* The initial state of the FormField.
*
* @member {object} state
* @returns {object}
*/
state() {
return {
error: null,
hasError: !1,
value: this.defaultValue ?? ""
};
},
/**
* Renders the FormField component.
*
* @returns {object}
*/
render() {
const e = this.name, t = this.getId(`${e}`), { label: s, description: o } = this, r = (l) => {
this.state.error = l, this.state.hasError = !!l;
};
return n({ class: "flex flex-auto space-y-4" }, [
xe([
we({ htmlFor: t }, s),
ke({
id: t,
name: e,
value: this.state.value,
setError: r
}, this.children),
o && ye({ id: this.getId("description") }, o),
n({ onState: ["error", (l) => l && ve(l)] })
])
]);
}
}
), Se = (e, t, s = null) => {
e.target.checkValidity() && (e.preventDefault(), s && s(e, t));
}, De = c(
(e, t) => R({ ...e, submit: (s, o) => Se(s, o, e.submit), class: `w-full ${e.class ?? ""}` }, t)
), bt = c((e, t) => n({ ...e, class: `space-y-6 p-4 md:p-6 divide-y ${e.class || ""}` }, t)), pt = c((e, t = []) => n({ class: "space-y-3 py-4" }, [
e.title && A({ class: "font-semibold" }, e.title),
...t
])), xt = (e, t) => n({ class: "flex justify-between" }, [
a({ class: "text-muted-foreground" }, e),
a(t)
]), Ie = ({ title: e, description: t, back: s, icon: o, options: r = [] }) => B({ class: "modal-header bg-background/80 backdrop-blur-md sticky flex flex-none items-center py-4 px-6 z-10" }, [
/**
* Back Button
*/
s && h({ variant: "icon", icon: u.arrows.left, class: "mr-2 p-0 flex sm:hidden", click: (l, i) => i.close() }),
/**
* Icon
*/
o && n({ class: "mr-2 w-12 h-12 rounded-full bg-muted flex flex-none items-center justify-center" }, [x(o)]),
/**
* Title and Description
*/
n({ class: "flex flex-auto flex-row justify-between w-full ml-2 gap-2" }, [
n({ class: "flex flex-auto flex-col" }, [
A({ class: "text-lg font-semibold m-0 truncate" }, e),
t && n({ class: "text-sm text-muted-foreground truncate" }, t)
]),
...r
])
]), Te = c((e, t) => n({
popover: "manual",
class: `modal m-auto top-0 right-0 bottom-0 left-0 fixed z-20 grid w-full h-full max-h-screen gap-2 lg:border bg-background text-foreground shadow-xl break-words p-0 ${e.class}`,
click: (s, o) => {
s.target === o.panel && (s.preventDefault(), s.stopPropagation(), o.state.open = !1);
}
}, [
De({ class: "modal-content relative bg-background z-[1] flex flex-auto flex-col space-y-4", submit: (s, o) => e.onSubmit && e.onSubmit(o) }, [
Ie(e),
n({ class: "modal-body flex flex-grow flex-col overflow-y-auto py-0 px-6 z-0" }, t),
M({ class: "modal-footer sticky bg-background/80 backdrop-blur-md flex flex-none justify-between py-4 px-6 z-10" }, e.buttons)
])
])), $e = (e) => U.render(e, app.root);
class wt extends p {
/**
* This will declare the props for the compiler.
*
* @returns {void}
*/
declareProps() {
this.title = null, this.description = null, this.size = null, this.type = null, this.hidePrimaryButton = !1, this.icon = null, this.onSubmit = null, this.onClose = null, this.back = !1;
}
/**
* This will render the modal component.
*
* @returns {object}
*/
render() {
const t = this.getMainClass(), s = this.title || "", o = this.description || null;
return Te(
{
class: t,
title: s,
description: o,
options: this.headerOptions(),
buttons: this.getButtons(),
onSubmit: (r) => {
this.onSubmit && this.onSubmit(r), this.destroy();
},
icon: this.icon,
back: this.back ?? !1,
aria: { expanded: ["open"] }
},
this.children
);
}
/**
* This will setup the states.
*
* @returns {object}
*/
setupStates() {
return {
open: {
state: !1,
callBack: (t) => {
t || this.destroy();
}
}
};
}
/**
* This will get the header options.
*
* @returns {Array<object>}
*/
headerOptions() {
return [];
}
/**
* This will get the buttons for the modal.
*
* @returns {array}
*/
getButtons() {
return [
h({ variant: "outline", click: () => this.destroy() }, "Cancel"),
this.hidePrimaryButton !== !0 && h({ variant: "primary", type: "submit" }, "Save")
];
}
/**
* This will check if the click was outside the component.
*
* @param {object} element
* @returns {boolean}
*/
isOutsideClick(t) {
return !this.panel.contains(t);
}
/**
* This will get the size class.
*
* @returns {string}
*/
getSizeClass() {
switch (this.size) {
// case 'sm':
// return 'sm max-w-[646px]';
case "lg":
return "lg max-w-[900px]";
case "xl":
return "xl max-w-[1400px]";
default:
return "md max-w-[760px]";
}
}
/**
* This will get the type class.
*
* @returns {string}
*/
getTypeClass() {
switch (this.type) {
case "right":
return "right right-0";
case "left":
return "left left-0";
default:
return "";
}
}
/**
* This will get the modal class.
*
* @returns {string}
*/
getMainClass() {
return this.getSizeClass() + " " + this.getTypeClass();
}
/**
* This will override the set up to use the app shell.
*
* @param {object} container
*/
setContainer(t) {
this.container = app.root;
}
/**
* This will open the modal.
*
* @returns {void}
*/
open() {
$e(this), this.showModal();
}
/**
* This will show the modal.
*
* @protected
* @returns {void}
*/
showModal() {
window.setTimeout(() => this.panel.showPopover(), 10), this.state.open = !0, document.documentElement.style.overflowY = "hidden";
}
/**
* This will hide the modal.
*
* @protected
* @returns {void}
*/
beforeDestroy() {
this.panel.hidePopover(), this.state.open = !1, typeof this.onClose == "function" && this.onClose(), document.documentElement.style.overflowY = "auto";
}
}
const F = {
info: {
bgColor: "bg-muted/10",
borderColor: "border-blue-500",
iconColor: "text-blue-500"
},
warning: {
bgColor: "bg-muted/10",
borderColor: "border-warning",
iconColor: "text-warning"
},
destructive: {
bgColor: "bg-muted/10",
borderColor: "border-destructive",
iconColor: "text-red-500"
},
success: {
bgColor: "bg-muted/10",
borderColor: "border-emerald-500",
iconColor: "text-emerald-500"
},
default: {
bgColor: "bg-muted/10",
borderColor: "border",
iconColor: "text-muted-foreground"
}
}, Ae = (e) => B({ class: "flex justify-center" }, [
G({ class: "text-lg font-bold mb-0" }, e)
]), Be = c(({ href: e, class: t }, s) => Y({
class: `pullRightIn bg-popover text-popover-foreground relative flex flex-auto flex-col justify-start shadow-lg pointer-events-auto p-4 border rounded-md min-w-[340px] max-w-[450px] mt-4 ${t}`,
href: e,
role: "alert"
}, s)), Me = c(({ close: e, class: t }, s) => n({
class: `pullRightIn bg-popover text-popover-foreground relative flex flex-auto flex-col justify-start shadow-lg pointer-events-auto p-4 border rounded-md min-w-[340px] max-w-[450px] mt-4 ${t}`,
click: () => e(),
role: "alert"
}, s));
class Le extends ce {
/**
* This will declare the props for the compiler.
*
* @returns {void}
*/
declareProps() {
this.removingClass = "pullRight", this.secondaryAction = null, this.primaryAction = null, this.primary = !1, this.secondary = !1, this.title = null, this.description = null, this.icon = null, this.onClick = null;
}
/**
* This will be called when the component is created.
*
* @returns {void}
*/
onCreated() {
this.duration = this.duration || 4e3;
}
/**
* This will render the component.
*
* @returns {object}
*/
render() {
const { bgColor: t, borderColor: s, iconColor: o } = this.getTypeStyles(), r = this.href || null, l = this.getChildren(o);
return r ? Be({
href: r,
class: `${t} ${s}`
}, l) : Me({
close: this.close.bind(this),
class: `${t} ${s}`
}, l);
}
/**
* This will be called after the component is set up.
*
* @returns {void}
*/
afterSetup() {
const t = this.duration;
t !== "infinite" && (this.timer = new oe(t, this.close.bind(this)), this.timer.start());
}
/**
* This will get the style properties based on the notification type.
*
* @returns {object}
*/
getTypeStyles() {
const t = this.type || "default";
return F[t] || F.default;
}
/**
* This will get the buttons for the notification.
*
* @returns {array}
*/
getButtons() {
return [
n({ class: "flex flex-row mt-6 gap-2" }, [
this.secondary && h({ variant: "outline", click: () => this.secondaryAction && this.secondaryAction() }, this.secondary),
this.primary && h({ click: () => this.primaryAction && this.primaryAction() }, this.primary)
])
];
}
/**
* This will get the children for the notification.
*
* @param {string} iconColor
* @returns {array}
*/
getChildren(t) {
return [
n({ class: "flex items-start" }, [
this.icon && g({ class: `mr-4 ${t}`, html: this.icon }),
n({ class: "flex flex-auto flex-col" }, [
n({ class: "flex flex-auto flex-row items-center w-full pr-12" }, [
this.title && Ae(this.title)
]),
b({ class: "text-base text-muted-foreground m-0 pr-12" }, this.description),
(this.primary || this.secondary) && M({ class: "margin-top-24 flex align-center" }, this.getButtons())
])
]),
h({
class: "absolute top-[12px] right-[12px]",
variant: "icon",
icon: u.x,
click: this.close.bind(this)
})
];
}
/**
* This will close the notification.
*
* @param {object} e The event object.
* @returns {void}
*/
close(t) {
t && t.stopPropagation(), this.duration !== "infinite" && this.timer.stop(), this.onClick && this.onClick(), this.destroy();
}
}
let Pe = 0;
class yt extends p {
/**
* This will render the component.
*
* @returns {object}
*/
render() {
return n({ class: "notification-container pointer-events-none inset-auto bg-transparent backdrop:bg-transparent overflow-visible fixed bottom-[80px] right-0 z-50 p-5", popover: "manual" }, [
new ne({
cache: "list",
key: "id",
role: "list",
rowItem: (t) => new Le(t)
})
]);
}
/**
* This will add a notification.
*
* @param {object} props
* @returns {void}
*/
addNotice(t = {}) {
t.id = Pe++, t.callBack = () => this.removeNotice(t), this.list.append([t]), this.panel.hidePopover(), this.panel.showPopover();
}
/**
* This will remove a notification.
*
* @param {object} notice
* @returns {void}
*/
removeNotice(t) {
this.list.delete(t.id);
}
}
const N = window.matchMedia, I = c(({ value: e, label: t, icon: s }) => m({
class: 'text-sm gap-1 font-medium leading-none disabled:cursor-not-allowed disabled:opacity-70 flex flex-col items-center justify-between rounded-md border-2 bg-popover p-4 hover:bg-accent hover:text-accent-foreground data-[state="active"]:border-primary [&:has([data-state="active"])]:border-primary',
onState: ["method", { active: e }],
dataSet: ["method", ["state", e, "active"]],
click: (o, { state: r }) => {
r.method = e, localStorage.setItem("theme", e), e === "system" && localStorage.removeItem("theme"), Fe(e);
}
}, [
x(s),
a(t)
])), Fe = (e) => {
var o;
const t = document.documentElement;
if (e === "system" && (e = (o = window.matchMedia) != null && o.call(window, "(prefers-color-scheme: dark)").matches ? "dark" : "light"), N && !N("(prefers-color-scheme: " + e + ")").matches) {
t.classList.add(e);
return;
}
const s = e === "light" ? "dark" : "light";
t.classList.remove(s);
}, vt = S(
{
/**
* This will render the component.
*
* @returns {object}
*/
render() {
return n({ class: "flex flex-auto flex-col" }, [
n({ class: "grid grid-cols-3 gap-4" }, [
I({ label: "System", value: "system", icon: u.adjustments.horizontal }),
I({ label: "Light", value: "light", icon: u.sun }),
I({ label: "Dark", value: "dark", icon: u.moon })
])
]);
},
/**
* This will setup the states.
*
* @returns {object}
*/
state() {
return {
method: window.localStorage.getItem("theme") ?? "system"
};
}
}
), Ct = w(
{
/**
* The initial state of the Toggle.
*
* @returns {object}
*/
state() {
return {
active: this.active ?? !1
};
},
/**
* This is added to check the checkbox after the component is rendered.
* to see if the bind updated the checked value.
*
* @returns {void}
*/
after() {
this.state.active = this.checkbox.checked;
},
/**
* Renders the Toggle component.
*
* @returns {object}
*/
render() {
return m({
class: "relative inline-flex h-6 w-11 min-w-11 items-center rounded-full bg-muted transition-colors focus:outline-none",
onState: ["active", { "bg-primary": !0, "bg-muted": !1 }],
click: (t, { state: s }) => {
s.toggle("active"), this.checkbox.checked = s.active;
}
}, [
J({
cache: "checkbox",
class: "opacity-0 absolute top-0 left-0 bottom-0 right-0 w-full h-full",
/**
* This will add the default checked before binding.
* If binding it will override the default checked value.
*/
checked: this.state.active,
bind: this.bind,
required: this.required
}),
a({
class: "absolute h-5 w-5 bg-background rounded-full shadow-md transform transition-transform",
onState: ["active", { "translate-x-[22px]": !0, "translate-x-[2px]": !1 }]
})
]);
}
}
), y = {
ONLINE: "online",
OFFLINE: "offline",
BUSY: "busy",
AWAY: "away"
}, f = {
ONLINE: "bg-green-500",
OFFLINE: "bg-gray-500",
BUSY: "bg-red-500",
AWAY: "bg-yellow-500"
}, Ne = (e = "") => (e = e.toUpperCase(), f[e] || f.OFFLINE), kt = (e) => n({
class: `absolute bottom-0 right-0 w-3 h-3 border-2 rounded-full ${Ne(e)}`
}), St = ({ propName: e = "status" } = {}) => n({
class: "absolute bottom-0 right-0 w-3 h-3 border-2 rounded-full",
onSet: [e, {
[f.ONLINE]: y.ONLINE,
[f.OFFLINE]: y.OFFLINE,
[f.BUSY]: y.BUSY,
[f.AWAY]: y.AWAY
}]
}), ze = (e, t) => Y(
{
href: e,
"aria-current": t === "Breadcrumb" && "page",
// Only set aria-current on the last item
class: "text-muted-foreground font-medium hover:text-foreground"
},
[a(t)]
), Ee = () => x({
class: "mx-3 text-muted-foreground",
"aria-hidden": !0,
size: "xs"
}, u.chevron.single.right), je = (e) => n({ class: "flex items-center" }, [
e.href ? ze(e.href, e.label) : a(e.label),
e.separator && Ee()
]), Dt = S(
{
/**
* Set initial data
*
* @returns {Data}
*/
setData() {
return new k({
// @ts-ignore
items: this.items || []
});
},
/**
* Render Breadcrumb Component
*
* @returns {object}
*/
render() {
const e = this.data.items.length - 1;
return K(
{
"aria-label": "Breadcrumb",
class: "flex items-center space-x-1 text-sm"
},
[
n({
role: "list",
class: "flex items-center",
for: ["items", (t, s) => je({
href: t.href,
label: t.label,
separator: s < e
})]
})
]
);
}
}
), z = {
xs: "h-1 w-1",
sm: "h-2 w-2",
md: "h-4 w-4",
lg: "h-8 w-8",
xl: "h-12 w-12",
"2xl": "h-16 w-16",
"3xl": "h-24 w-24",
default: "h-4 w-4"
}, Oe = (e) => z[e] || z.default, Ve = ({ index: e, size: t }) => n({ class: `${t} rounded-full bg-muted cursor-pointer` }, [
a({
class: "block w-full h-full rounded-full transition-colors",
onSet: ["activeIndex", {
"bg-primary": e,
"shadow-md": e
}],
click: (s, { data: o, onClick: r }) => {
o.activeIndex = e, r && r(e);
}
})
]), Ye = (e, t) => Array.from({ length: e }, (s, o) => Ve({
index: o,
size: t
})), It = S(
{
/**
* Defines component data (props).
*
* @returns {Data}
*/
setData() {
return new k({
// @ts-ignore
count: this.count || 4,
// total dots
// @ts-ignore
activeIndex: this.activeIndex || 0
});
},
/**
* Renders the dots.
*
* @returns {object}
*/
render() {
const e = this.gap || "gap-2", t = Oe(this.size || "sm"), s = Ye(this.data.count, t);
return n(
{ class: "flex justify-center items-center py-2" },
[
n({ class: `flex ${e}` }, s)
]
);
}
}
), Ue = ({ toggleDropdown: e }) => m(
{
cache: "button",
class: "relative z-[2] inline-flex items-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-muted h-10 px-4 py-2 justify-between",
click: e
},
[
a({ onState: ["selectedLabel", (t) => t || "Select item..."] }),
g({ html: u.chevron.upDown })
]
), qe = (e, t, s) => O({
class: "flex flex-auto items-center cursor-pointer p-2 hover:bg-muted/50 rounded-sm",
click: () => t(e),
onState: [s, "selectedValue", { "bg-secondary": e.value }]
}, [
e.icon && a({ class: "mr-2 flex items-baseline" }, [x({ size: "xs" }, e.icon)]),
a({ class: "text-base font-normal" }, e.label)
]), He = (e, t) => n({ class: "w-full border rounded-md" }, [
V({ class: "max-h-60 overflow-y-auto p-2 grid gap-1", for: ["items", (s) => qe(s, e, t)] })
]), _e = ({ onSelect: e, state: t }) => n({ class: "flex flex-auto flex-col" }, [
v(
"open",
(s, o, r) => s ? new D({
cache: "dropdown",
parent: r,
button: r.button
}, [
He(e, t)
]) : null
)
]), Tt = S(
{
/**
* This will set up the data.
*
* @returns {Data}
*/
setData() {
return new k({
// @ts-ignore
items: this.items || []
});
},
/**
* This will set up the states.
*
* @returns {object}
*/
state() {
return {
open: !1,
selectedLabel: "",
selectedValue: ""
};
},
/**
* This will set the state item.
*
* @param {object} item
* @returns {void}
*/
setStateItem(e) {
const t = this.state;
t.selectedValue = e.value, t.selectedLabel = e.label, t.open = !1;
},
/**
* Handles the selection of an item.
*
* @param {object} item
* @returns {void}
*/
select(e) {
this.setStateItem(e), typeof this.onSelect == "function" && this.onSelect(e, this.parent);
},
/**
* Selects the first item in the list.
*
* @returns {void}
*/
selectFirstItem() {
const e = this.data.items[0];
this.select(e);
},
/**
* Toggles the dropdown open state.
*
* @returns {void}
*/
toggleDropdown() {
this.state.toggle("open");
},
/**
* This will run after the component is set up.
*
* @returns {void}
*/
after() {
if (this.selectFirst === !0 && this.state.selectedValue === "") {
const e = this.data.items[0];
e && this.setStateItem(e);
}
},
/**
* This will render the component.
*
* @returns {object}
*/
render() {
const e = this.class || "", t = this.maxWidth || "max-w-[250px]", s = this.width || "w-full";
return n({ class: `relative ${s} flex flex-auto flex-col ${t} ${e}` }, [
// @ts-ignore
Ue({ toggleDropdown: this.toggleDropdown.bind(this) }),
_e({
// @ts-ignore
state: this.state,
// @ts-ignore
onSelect: this.select.bind(this)
}),
// Hidden required input for form validation
// @ts-ignore
this.required && C({
class: "opacity-0 absolute top-0 left-0 z-[1]",
type: "text",
// @ts-ignore
name: this.name,
required: !0,
// @ts-ignore
value: ["[[selectedValue]]", this.state]
})
]);
}
}
), H = ({ icon: e, click: t, ariaLabel: s }) => h({
variant: "icon",
class: "flex flex-none",
click: t,
icon: e,
"aria-label": s
}), We = ({ click: e }) => H({
icon: u.circleMinus,
click: e,
ariaLabel: "Decrement"
}), Re = ({ click: e }) => H({
icon: u.circlePlus,
click: e,
ariaLabel: "Increment"
}), Ge = ({ bind: e, min: t, max: s, readonly: o = !1 }) => Q(({ state: r }) => C({
value: ["[[count]]", r],
bind: e,
blur: (l, { state: i }) => {
let d = parseInt(l.target.value, 10);
isNaN(d) && (d = t ?? 0), t !== void 0 && (d = Math.max(d, t)), s !== void 0 && (d = Math.min(d, s)), i.count = d;
},
class: "flex flex-auto text-lg font-medium bg-transparent text-center border min-w-0",
readonly: o,
min: t,
max: s,
type: "number",
"aria-label": "Counter"
})), $t = w(
{
/**
* Initial state for the counter component.
*
* @member {object} state
*/
state() {
return {
count: {
state: this.initialCount ?? 0,
callBack: (e) => this.change && this.change(e)
}
};
},
/**
* Renders the Counter component.
*
* @returns {object}
*/
render() {
const e = this.class ?? "";
return n({ class: `flex flex-auto items-center justify-between space-x-4 p-4 ${e}` }, [
We({ click: () => this.state.decrement("count") }),
Ge({
bind: this.bind,
readonly: this.readonly,
min: this.min,
max: this.max
}),
Re({ click: () => this.state.increment("count") })
]);
}
}
), Je = ({ bind: e, required: t }) => C({
cache: "input",
class: "opacity-0 absolute top-0 left-0 w-full h-full pointer-events-none",
bind: e,
required: t
}), Ke = ({ bind: e, required: t, toggleOpen: s }) => m({
class: "relative flex items-center gap-2 w-full justify-between border border-input bg-background hover:bg-muted rounded-md h-10 px-4 py-2",
click: s
}, [
Je({ bind: e, required: t }),
a({
onState: ["selectedDate", (o) => o ? $.format("standard", o) : "Pick a date"]
}),
g({ html: u.calendar.days })
]), Qe = ({ handleDateSelect: e, blockPriorDates: t }) => n({ class: "absolute mt-1 z-10 bg-background rounded-md shadow-lg" }, [
v(
"open",
(s, o, r) => s ? new D({
cache: "dropdown",
parent: r,
button: r.panel,
size: "fit"
}, [
new se({
selectedDate: r.state.selectedDate,
selectedCallBack: e,
blockPriorDates: t
})
]) : null
)
]), At = w(
{
/**
* The initial state of the DatePicker.
*
* @member {object} state
*/
state() {
return {
selectedDate: this.selectedDate ?? null,
open: !1
};
},
/**
* This is added to check the input after the component is rendered.
* to see if the bind updated the input value.
*
* @returns {void}
*/
after() {
this.state.selectedDate = this.input.value;
},
/**
* Renders the DatePicker component.
*
* @returns {object}
*/
render() {
const e = (s, { state: o }) => o.toggle("open"), t = (s) => {
this.state.selectedDate = s, this.state.open = !1, this.input.value = s, typeof this.onChange == "function" && this.onChange(s);
};
return n({ class: "relative w-full max-w-[320px]" }, [
Ke({
toggleOpen: e,
bind: this.bind,
required: this.required
}),
Qe({
handleDateSelect: t,
blockPriorDates: this.blockPriorDates || !1
})
]);
}
}
), Bt = ({ dateTime: e = "", remoteTimeZone: t = "America/Denver", filter: s = null }) => X([
new re({
dateTime: e,
filter: s || ((o) => {
const r = $.getLocalTime(o, !0, !1, t);
return $.getTimeFrame(r);
})
})
]);
function Xe({ bind: e, required: t }) {
return C({
cache: "input",
class: "opacity-0 absolute top-0 left-0 w-full h-full pointer-events-none",
bind: e,
required: t
});
}
function Ze({ bind: e, required: t, toggleOpen: s }) {
return m(
{
class: "relative flex items-center gap-2 w-full justify-between border border-input bg-background hover:bg-muted rounded-md h-10 px-4 py-2",
click: s
},
[
Xe({ bind: e, required: t }),
a({
onState: ["selectedTime", (o) => o || "Pick a time"]
}),
g({ html: u.clock })
]
);
}
function T({ items: e, handleTimeSelect: t, state: s, stateValue: o, pad: r = !1 }) {
return n(
{ class: "flex flex-col max-h-[200px] overflow-y-auto" },
e.map((l) => {
let i = r ? l.toString().padStart(2, "0") : l.toString();
return m({
text: i,
class: "hover:bg-muted/50 rounded-md px-2 py-1",
click: () => t({ [o]: i }),
onState: [s, o, { "bg-muted": i }]
});
})
);
}
function et({ handleTimeSelect: e }) {
return n(
{ class: "absolute mt-1 z-10 bg-background rounded-md shadow-lg" },
[
v(
"open",
(t, s, o) => t ? new D(
{
cache: "dropdown",
parent: o,
button: o.panel,
size: "fit"
},
[
n(
{ class: "flex flex-auto flex-col border rounded-md shadow-md" },
[
n(
{ class: "grid grid-cols-3 gap-2 p-4 text-center max-h-[220px] min-w-[240px]" },
[
// Hours column
T({
items: Array.from({ length: 12 }, (r, l) => l + 1),
handleTimeSelect: e,
state: o.state,
stateValue: "hour",
pad: !0
}),
// Minutes column
T({
items: Array.from({ length: 60 }, (r, l) => l),
handleTimeSelect: e,
state: o.state,
stateValue: "minute",
pad: !0
}),
// AM/PM column
T({
items: ["AM", "PM"],
handleTimeSelect: e,
state: o.state,
stateValue: "meridian"
})
]
)
]
)
]
) : null
)
]
);
}
function E(e) {
if (!e)
return { hour: null, minute: null, meridian: null };
const t = /^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM)?$/i, s = e.match(t);
if (!s)
return { hour: null, minute: null, meridian: null };
let [, o, r, , l] = s, i = parseInt(o, 10), d = parseInt(r, 10);
return i < 0 || i > 23 || d < 0 || d > 59 ? { hour: null, minute: null, meridian: null } : (l ? (l = l.toUpperCase(), l === "PM" && i < 12 ? i += 12 : l === "AM" && i === 12 && (i = 12)) : i === 0 ? (l = "AM", i = 12) : i < 12 ? l = "AM" : i === 12 ? l = "PM" : (l = "PM", i -= 12), {
hour: i.toString().padStart(2, "0"),
minute: d.toString().padStart(2, "0"),
meridian: l
});
}
const Mt = w(
{
/**
* The initial shallow state of the TimePicker.
*
* @member {object} state
*/
state() {
const e = this.selectedTime ?? null, { hour: t, minute: s, meridian: o } = E(e);
return {
selectedTime: e,
open: !1,
hour: t,
minute: s,
meridian: o
};
},
/**
* Updates the state after the input is rendered.
*
* @returns {void}
*/
after() {
if (this.input.value) {
const { hour: e, minute: t, meridian: s } = E(this.input.value);
this.state.set({
hour: e,
minute: t,
meridian: s,
selectedTime: this.input.value
});
}
},
/**
* Renders the TimePicker component.
*
* @returns {object}
*/
render() {
const e = (s, { state: o }) => o.toggle("open"), t = ({ hour: s, minute: o, meridian: r }) => {
if (s && (this.state.hour = s), o && (this.state.minute = o), r && (this.state.meridian = r), this.state.hour && this.state.minute && this.state.meridian) {
const l = `${this.state.hour}:${this.state.minute} ${this.state.meridian}`;
this.state.selectedTime = l, this.state.open = !1, this.input.value = l, typeof this.change == "function" && this.change(l);
}
};
return n(
{ class: "relative w-full max-w-[320px]" },
[
Ze({
toggleOpen: e,
bind: this.bind,
required: this.required
}),
et({
handleTimeSelect: t
})
]
);
}
}
), tt = (e, t) => n({ class: `hidden md:flex items-start justify-center w-6 h-6 mr-3 ${t}` }, [
x({ size: "lg" }, e)
]), st = ({ title: e }) => B({ class: "flex flex-auto items-center" }, [
A({ class: "text-lg font-semibold" }, e)
]), ot = c((e, t) => Z(
{
class: `fixed pullUpIn z-30 w-[98%] border md:w-full max-w-lg bg-popover text-foreground shadow-lg duration-200
rounded-lg flex flex-auto flex-col
bottom-4 top-auto inset-auto m-auto md:bottom-0 md:top-0 left-0 right-0 ${e.class}`,
click: e.click,
aria: { expanded: ["open"] }
},
[
n({ class: "flex flex-auto p-6 pb-12 md:pb-6" }, [
// Icon and content
e.icon && tt(e.icon, e.iconColor),
n({ class: "flex flex-auto flex-col gap-4" }, [
n({ class: "flex flex-auto flex-col space-y-2" }, [
st(e),
e.description && b({ class: "flex flex-auto flex-col text-sm text-muted-foreground" }, e.description),
n({ class: "flex flex-auto flex-col text-sm text-muted-foreground" }, t)
]),
e.buttons && M({ class: "flex flex-col-reverse sm:flex-row sm:justify-end mt-6 gap-2 sm:gap-0 sm:space-x-2" }, e.buttons)
])
])
]
)), nt = (e) => U.render(e, app.root), j = {
info: {
borderColor: "border-blue-500",
bgColor: "bg-muted/10",
iconColor: "text-blue-500"
},
warning: {
bgColor: "bg-muted/10",
borderColor: "border-warning",
iconColor: "text-warning"
},
destructive: {
bgColor: "bg-muted/10",
borderColor: "border-destructive",
iconColor: "text-red-500"
},
success: {
bgColor: "bg-muted/10",
borderColor: "border-emerald-500",
iconColor: "text-emerald-500"
},
default: {
borderColor: "border",
bgColor: "bg-muted/10",
iconColor: "text-muted-foreground"
}
};
class rt extends p {
/**
* This will declare the props for the compiler.
*
* @returns {void}
*/
declareProps() {
this.title = null, this.description = null, this.type = "", this.icon = null, this.onClose = null, this.hideFooter = !1, this.buttons = null;
}
/**
* This will render the modal component.
*
* @returns {object}
*/
render() {
const t = (d) => {
d.target === this.panel && this.close();
}, { borderColor: s, bgColor: o, iconColor: r } = j[this.type] || j.default, l = `${this.getMainClass()} ${o} ${s}`, i = this.title || "Dialog Title";
return ot({
class: l,
title: i,
click: t,
icon: this.icon,
iconColor: r,
description: this.description,
buttons: this.getButtons()
}, this.children);
}
/**
* This will get the buttons for the modal.
*
* @returns {array}
*/
getButtons() {
return this.hideFooter ? null : this.buttons ? this.buttons : [
h({ variant: "outline", click: () => this.close() }, "Close")
];
}
/**
* This will setup the states.
*
* @returns {object}
*/
setupStates() {
return {
open: !1
};
}
/**
* This will get the modal class.
*
* @returns {string}
*/
getMainClass() {
return "";
}
/**
* This will open the modal.
*
* @returns {void}
*/
open() {
nt(this), this.panel.showModal(), this.state.open = !0;
}
/**
* This will close the modal.
*
* @returns {void}
*/
close() {
this.state.open = !1, this.panel.close(), typeof this.onClose == "function" && this.onClose(), this.destroy();
}
}
class Lt extends rt {
/**
* This will declare the props for the compiler.
*
* @returns {void}
*/
declareProps() {
this.confirmTextLabel = null, this.confirmed = null;
}
/**
* This will get the buttons for the modal.
*
* @returns {array}
*/
getButtons() {
const t = this.confirmTextLabel || "Confirm";
return [
h({ variant: "outline", click: () => this.close() }, "Cancel"),
h({ variant: "primary", click: () => this.confirm() }, t)
];
}
/**
* This will confirm the action.
*
* @returns {void}
*/
confirm() {
this.confirmed && this.confirmed(), this.close();
}
}
export {
mt as A,
Dt as B,
Tt as C,
ce as D,
ot as E,
xe as F,
rt as G,
wt as M,
yt as N,
Re as P,
xt as S,
vt as T,
me as a,
ft as b,
ge as c,
we as d,
ye as e,
ve as f,
ke as g,
gt as h,
De as i,
bt as j,
pt as k,
Le as l,
Ct as m,
kt as n,
St as o,
y as p,
f as q,
Ne as r,
It as s,
We as t,
Ge as u,
$t as v,
At as w,
Bt as x,
Mt as y,
Lt as z
};