adapt new Input
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s

This commit is contained in:
2026-04-23 13:22:49 +02:00
parent 59e6d972a8
commit e842ed8041
61 changed files with 2553 additions and 2758 deletions

View File

@@ -54,7 +54,7 @@ import "sigpro-ui/css";
const App = () => { const App = () => {
const show = $(false); const show = $(false);
return Button( return button(
{ {
class: "btn-primary", class: "btn-primary",
onclick: () => show(true) onclick: () => show(true)
@@ -77,7 +77,7 @@ import "sigpro-ui/css";
// All components (Button, Table, Input, Alert, etc.) are now globally available. // All components (Button, Table, Input, Alert, etc.) are now globally available.
// No need to import anything else! // No need to import anything else!
const myApp = () => Table({ items: [], columns: [] }); const myApp = () => table({ items: [], columns: [] });
``` ```
--- ---
@@ -91,10 +91,10 @@ import "sigpro-ui/css";
const App = () => { const App = () => {
const count = $(0); const count = $(0);
return Div({ class: "p-10 flex flex-col gap-4" }, [ return div({ class: "p-10 flex flex-col gap-4" }, [
H1({ class: "text-2xl font-bold" }, "Welcome to SigPro UI"), H1({ class: "text-2xl font-bold" }, "Welcome to SigPro UI"),
Button({ button({
class: "btn-primary", class: "btn-primary",
onclick: () => { onclick: () => {
count(c => c + 1); count(c => c + 1);
@@ -148,7 +148,7 @@ import { tt, Locale } from "sigpro-ui";
Locale('en'); Locale('en');
// Use translations // Use translations
const closeButton = Button({}, tt('close')()); const closeButton = button({}, tt('close')());
``` ```
--- ---

View File

@@ -1,7 +1,7 @@
// components/Accordion.js // components/Accordion.js
import { h } from "sigpro"; import { h } from "sigpro";
export const Accordion = (props) => { export const Accordion = (props, children) => {
const name = props.name || `accordion-${Math.random().toString(36).slice(2, 9)}`; const name = props.name || `accordion-${Math.random().toString(36).slice(2, 9)}`;
if (props.items && Array.isArray(props.items)) { if (props.items && Array.isArray(props.items)) {
@@ -9,7 +9,7 @@ export const Accordion = (props) => {
props.items.map(item => h("div", { class: `collapse ${item.class ?? ''}` }, [ props.items.map(item => h("div", { class: `collapse ${item.class ?? ''}` }, [
h("input", { type: "radio", name, checked: item.open }), h("input", { type: "radio", name, checked: item.open }),
h("div", { class: "collapse-title text-xl font-medium" }, item.title), h("div", { class: "collapse-title text-xl font-medium" }, item.title),
h("div", { class: "collapse-content" }, item.children) h("div", { class: "collapse-content" }, children)
])) ]))
); );
} }
@@ -17,6 +17,6 @@ export const Accordion = (props) => {
return h("div", { class: `collapse ${props.class ?? ''}` }, [ return h("div", { class: `collapse ${props.class ?? ''}` }, [
h("input", { type: "radio", name, checked: props.open }), h("input", { type: "radio", name, checked: props.open }),
h("div", { class: "collapse-title text-xl font-medium" }, props.title), h("div", { class: "collapse-title text-xl font-medium" }, props.title),
h("div", { class: "collapse-content" }, props.children) h("div", { class: "collapse-content" }, children)
]); ]);
}; };

View File

@@ -1,6 +1,6 @@
// components/Badge.js // components/Badge.js
import { h } from "sigpro"; import { h } from "sigpro";
const colors = [""]
export const Badge = (props, children) => { export const Badge = (props, children) => {
children === undefined && (children = props, props = {}); children === undefined && (children = props, props = {});
return h("span", { ...props, class: `badge ${props.class ?? ''}` }, children); return h("span", { ...props, class: `badge ${props.class ?? ''}` }, children);

View File

@@ -1,6 +1,6 @@
// components/Datepicker.js // components/Datepicker.js
import { $, h, when, watch } from "sigpro"; import { $, h, when, watch } from "sigpro";
import { Calendar } from "./calendar.js"; import { Calendar } from "./Calendar.js";
export const Datepicker = (props) => { export const Datepicker = (props) => {
const isOpen = $(false); const isOpen = $(false);

60
components/Input.js Normal file
View File

@@ -0,0 +1,60 @@
import { h, $, when, fx } from 'sigpro';
import { get, cls, isFunc } from './_core.js';
export const Input = (props) => {
const { label, icon, float, placeholder, value, left, right, content, ...rest } = props;
const showPassword = $(false);
const isFocused = $(false);
const isPassword = props.type === 'password';
const inputType = () => isPassword
? (get(showPassword) ? 'text' : 'password')
: (props.type || 'text');
return h("div", {
class: "input-container",
onfocusin: () => isFocused(true),
onfocusout: (e) => {
if (!e.currentTarget.contains(e.relatedTarget)) {
isFocused(false);
}
}
}, [
h('label', { class: "floating-label" }, [
float ? h("span", {}, label) : null,
h("label", {
class: () => cls('input', props.class)
}, [
label && !float ? h('span', { class: 'label' }, label) : null,
left ?? null,
h('input', {
...rest,
type: inputType,
class: 'grow',
placeholder: placeholder || label || ' ',
value: value
}),
right ?? null,
isPassword ? h('label', { class: 'swap swap-rotate ml-2' }, [
h('input', {
type: 'checkbox',
onchange: (e) => showPassword(e.target.checked)
}),
h('span', { class: 'swap-on icon-[lucide--eye]' }),
h('span', { class: 'swap-off icon-[lucide--eye-off]' })
]) : null
]),
when(isFocused, () => fx({ duration: 300, slide: true },
h('div', {
class: 'input-content',
onmousedown: e => e.preventDefault()
}, [
isFunc(content) ? content(isFocused) : content
])
))
])
]);
};

58
components/InputBase.js Normal file
View File

@@ -0,0 +1,58 @@
import { h, $ } from 'sigpro.js';
import { ui, cls, get } from './_core.js';
export const InputBase = ({
loading = false,
ui: uiOptions = '',
class: className = '',
type = 'text',
value,
onInput,
...inputProps
}) => {
const isPassword = type === 'password';
const showPassword = $(false);
const inputClasses = cls(
ui('input', uiOptions),
className,
isPassword && 'pr-10',
loading && 'loading loading-spinner loading-xs absolute right-2 top-1/2 -translate-y-1/2'
);
let inputEl = h('input', {
class: inputClasses + (isPassword ? ' pr-10' : ''),
type: isPassword ? 'text' : 'password',
value,
oninput: onInput,
...inputProps
});
if (isPassword) {
const toggle = h('label', {
class: 'swap swap-rotate absolute right-2 top-1/2 -translate-y-1/2 cursor-pointer'
}, [
h('input', {
type: 'checkbox',
checked: showPassword(),
onchange: (e) => showPassword(e.target.checked)
}),
h('span', { class: 'swap-on icon-[lucide--eye]' }),
h('span', { class: 'swap-off icon-[lucide--eye-off]' })
]);
inputEl = h('div', { class: 'relative w-full' }, [inputEl, toggle]);
}
if (icon) {
const isIconClass = icon.includes('-') || icon.includes('icon-');
const iconElement = isIconClass
? h('span', { class: icon })
: h('span', { class: 'opacity-50' }, icon);
content = h('label', { class: ui('input', uiOptions).replace('input-', '') }, [
iconElement,
h('span', { class: 'opacity-70' })
]);
}
return inputEl;
};

61
components/_core.js Normal file
View File

@@ -0,0 +1,61 @@
// _core.js
import { $, watch } from 'sigpro';
export const ui = (base, extras = '') => {
if (!extras) return base;
const extraClasses = extras
.split(' ')
.map(part => part.trim())
.filter(Boolean)
.map(part => part.startsWith(base + '-') ? part : `${base}-${part}`)
.join(' ');
return `${base} ${extraClasses}`.trim();
};
export const get = val => typeof val === "function" ? val() : val;
export const filterBy = (items, query, field = 'label') => {
const q = String(query).toLowerCase();
if (!q) return get(items);
return get(items).filter(item => {
const text = typeof item === 'string' ? item : item[field];
return String(text).toLowerCase().includes(q);
});
};
export const listKey = (items, isOpen) => {
const cursor = $(-1);
watch([items, isOpen], () => {
if (!get(isOpen)) cursor(-1);
});
const onKey = (e, select) => {
const list = get(items);
if (!list.length) return;
if (e.key === 'ArrowDown') {
e.preventDefault();
isOpen(true);
cursor(Math.min(cursor() + 1, list.length - 1));
} else if (e.key === 'ArrowUp') {
e.preventDefault();
cursor(Math.max(cursor() - 1, 0));
} else if (e.key === 'Enter' && cursor() >= 0) {
e.preventDefault();
select(list[cursor()]);
} else if (e.key === 'Escape') {
isOpen(false);
}
};
return { cursor, onKey };
};
export const cls = (...classes) => classes.filter(Boolean).join(' ').trim();
export const getBy = (item, field = 'label') => {
return typeof item === 'string' ? item : item[field];
};
export const isFunc = f => typeof f === "function";

View File

@@ -1,13 +0,0 @@
// components/Input.js
import { h } from "sigpro";
export const Input = (props) => h("input", { ...props, class: `input ${props.class ?? ''}` });
export const InputLabel = (props) => h("label", { class: `${props.float ? 'floating-label' : 'input'}` },
[
h("span", { class: props.float ? '' : 'label opacity-50' }, props.label),
props.left ?? null,
h("input", { ...props, class: `${props.float ? 'input' : ''} ${props.class ?? ''}` }),
props.right ?? null
]
);

114
dist/sigpro-ui.css vendored
View File

@@ -3101,6 +3101,9 @@
.top-0 { .top-0 {
top: calc(var(--spacing) * 0); top: calc(var(--spacing) * 0);
} }
.top-1\/2 {
top: calc(1 / 2 * 100%);
}
.top-2 { .top-2 {
top: calc(var(--spacing) * 2); top: calc(var(--spacing) * 2);
} }
@@ -3122,6 +3125,9 @@
.right-1\/4 { .right-1\/4 {
right: calc(1 / 4 * 100%); right: calc(1 / 4 * 100%);
} }
.right-2 {
right: calc(var(--spacing) * 2);
}
.right-3 { .right-3 {
right: calc(var(--spacing) * 3); right: calc(var(--spacing) * 3);
} }
@@ -4153,6 +4159,19 @@
mask-size: 100% 100%; mask-size: 100% 100%;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M21.801 10A10 10 0 1 1 17 3.335'/%3E%3Cpath d='m9 11l3 3L22 4'/%3E%3C/g%3E%3C/svg%3E"); --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cg fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M21.801 10A10 10 0 1 1 17 3.335'/%3E%3Cpath d='m9 11l3 3L22 4'/%3E%3C/g%3E%3C/svg%3E");
} }
.icon-\[lucide--check\] {
display: inline-block;
width: 1em;
height: 1em;
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M20 6L9 17l-5-5'/%3E%3C/svg%3E");
}
.icon-\[lucide--chevron-left\] { .icon-\[lucide--chevron-left\] {
display: inline-block; display: inline-block;
width: 1em; width: 1em;
@@ -4831,6 +4850,11 @@
width: 100%; width: 100%;
} }
} }
.loading-xs {
@layer daisyui.l1.l2 {
width: calc(var(--size-selector, 0.25rem) * 4);
}
}
.w-3\.5 { .w-3\.5 {
width: calc(var(--spacing) * 3.5); width: calc(var(--spacing) * 3.5);
} }
@@ -4941,6 +4965,10 @@
--tw-translate-x: 100%; --tw-translate-x: 100%;
translate: var(--tw-translate-x) var(--tw-translate-y); translate: var(--tw-translate-x) var(--tw-translate-y);
} }
.-translate-y-1\/2 {
--tw-translate-y: calc(calc(1 / 2 * 100%) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
.translate-y-2 { .translate-y-2 {
--tw-translate-y: calc(var(--spacing) * 2); --tw-translate-y: calc(var(--spacing) * 2);
translate: var(--tw-translate-x) var(--tw-translate-y); translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -5395,12 +5423,6 @@
.border-primary { .border-primary {
border-color: var(--color-primary); border-color: var(--color-primary);
} }
.border-primary\/20 {
border-color: var(--color-primary);
@supports (color: color-mix(in lab, red, red)) {
border-color: color-mix(in oklab, var(--color-primary) 20%, transparent);
}
}
.border-transparent { .border-transparent {
border-color: transparent; border-color: transparent;
} }
@@ -6992,13 +7014,6 @@
} }
} }
} }
.hover\:bg-base-100 {
&:hover {
@media (hover: hover) {
background-color: var(--color-base-100);
}
}
}
.hover\:bg-base-200 { .hover\:bg-base-200 {
&:hover { &:hover {
@media (hover: hover) { @media (hover: hover) {
@@ -7128,48 +7143,15 @@
:root { :root {
font-size: 14px; font-size: 14px;
} }
.input, .select, .textarea { .input, .label, .select, .textarea {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:focus, &:focus-within { &:focus, &:focus-within {
outline: 1px solid transparent !important; outline: none !important;
outline-offset: 1px !important; box-shadow: 0 0 4px 0px;
} }
&:hover:not(:focus) { &:hover:not(:focus) {
background-color: oklch(from var(--color-base-100) calc(l - 0.03) c h); background-color: oklch(from var(--color-base-100) calc(l - 0.03) c h);
} }
&:focus {
--focus-color: var(--color-primary);
&[class*="-secondary"] {
--focus-color: var(--color-secondary);
}
&[class*="-accent"] {
--focus-color: var(--color-accent);
}
&[class*="-neutral"] {
--focus-color: var(--color-neutral);
}
&[class*="-ghost"] {
--focus-color: var(--color-base-content);
}
&[class*="-info"] {
--focus-color: var(--color-info);
}
&[class*="-success"] {
--focus-color: var(--color-success);
}
&[class*="-warning"] {
--focus-color: var(--color-warning);
}
&[class*="-error"] {
--focus-color: var(--color-error);
}
background-color: oklch(from var(--focus-color) l c h / 0.05);
border-color: var(--focus-color);
box-shadow: 0 0 0 4px oklch(from var(--focus-color) l c h / 0.25);
&[class*="-ghost"] {
border-width: 1px;
}
}
} }
.floating-label span { .floating-label span {
color: oklch(30% 0.01 260); color: oklch(30% 0.01 260);
@@ -7188,6 +7170,15 @@
animation: tabFadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1); animation: tabFadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
transform-origin: top; transform-origin: top;
} }
.input-content {
position: absolute;
top: 100%;
left: 0;
width: 100%;
z-index: 100;
background: white;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
@keyframes tabFadeIn { @keyframes tabFadeIn {
from { from {
opacity: 0; opacity: 0;
@@ -7198,6 +7189,31 @@
transform: scaleY(1); transform: scaleY(1);
} }
} }
@layer utilities {
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(-8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fade-out {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-8px);
}
}
.animate-fade-in {
animation: fade-in 0.15s ease-out forwards;
}
}
@layer base { @layer base {
:where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light] { :where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light] {
color-scheme: light; color-scheme: light;

1106
dist/sigpro-ui.esm.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1106
dist/sigpro-ui.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -72,9 +72,9 @@ Modal({
open: isVisible, open: isVisible,
title: "Precision Engineering" title: "Precision Engineering"
}, () => }, () =>
Div({ class: "space-y-4" }, [ div({ class: "space-y-4" }, [
P("SigPro-UI provides instant reactivity out of the box."), p("SigPro-UI provides instant reactivity out of the box."),
Button({ button({
class: "btn-primary", class: "btn-primary",
onclick: () => isVisible(false) onclick: () => isVisible(false)
}, "Confirm") }, "Confirm")

View File

@@ -9,7 +9,7 @@ Collapsible accordion component for organizing content into expandable sections.
## Props ## Props
| Prop | Type | Default | Description | | Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- | | :--------- | :--------------------------- | :--------------- | :----------------------------------------- |
| `title` | `string \| VNode \| Signal` | Required | Accordion section title | | `title` | `string \| VNode \| Signal` | Required | Accordion section title |
| `open` | `boolean \| Signal<boolean>` | `false` | Whether the accordion is expanded | | `open` | `boolean \| Signal<boolean>` | `false` | Whether the accordion is expanded |
| `name` | `string` | `auto-generated` | Group name for radio-style accordions | | `name` | `string` | `auto-generated` | Group name for radio-style accordions |
@@ -36,354 +36,33 @@ const BasicDemo = () => {
const open2 = $(false); const open2 = $(false);
const open3 = $(false); const open3 = $(false);
return Div({ class: 'flex flex-col gap-2' }, [ return div({ class: "flex flex-col gap-2" }, [
Accordion({ Accordion(
title: 'Section 1',
open: open1,
children: Div({ class: 'p-2' }, 'Content for section 1. This is a basic accordion section.')
}),
Accordion({
title: 'Section 2',
open: open2,
children: Div({ class: 'p-2' }, 'Content for section 2. You can put any content here.')
}),
Accordion({
title: 'Section 3',
open: open3,
children: Div({ class: 'p-2' }, 'Content for section 3. Accordions are great for FAQs.')
})
]);
};
mount(BasicDemo, '#demo-basic');
```
### Group Accordion (Radio Style)
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-group" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Accordion, Div, mount } = window;
const GroupDemo = () => {
const openSection = $('section1');
return Div({ class: 'flex flex-col gap-2' }, [
Accordion({
name: 'group',
title: 'Section 1',
open: () => openSection() === 'section1',
children: Div({ class: 'p-2' }, 'Content for section 1. Only one section can be open at a time.')
}),
Accordion({
name: 'group',
title: 'Section 2',
open: () => openSection() === 'section2',
children: Div({ class: 'p-2' }, 'Content for section 2. Opening this will close section 1.')
}),
Accordion({
name: 'group',
title: 'Section 3',
open: () => openSection() === 'section3',
children: Div({ class: 'p-2' }, 'Content for section 3. This is useful for FAQ sections.')
})
]);
};
mount(GroupDemo, '#demo-group');
```
### Using Items Array
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-items" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Accordion, Div, mount } = window;
const ItemsDemo = () => {
const openItems = $({
item1: true,
item2: false,
item3: false
});
return Accordion({
items: [
{ {
title: 'First Item', title: "Section 1",
open: () => openItems().item1, open: open1,
children: Div({ class: 'p-2' }, 'This is the content of the first item.')
}, },
{ div(
title: 'Second Item', { class: "p-2" },
open: () => openItems().item2, "Content for section 1. This is a basic accordion section.",
children: Div({ class: 'p-2' }, 'This is the content of the second item.') ),
}, ),
{
title: 'Third Item',
open: () => openItems().item3,
children: Div({ class: 'p-2' }, 'This is the content of the third item.')
}
]
});
};
mount(ItemsDemo, '#demo-items');
```
### FAQ Accordion
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-faq" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Accordion, Div, mount } = window;
const FaqDemo = () => {
const openFaq = $('faq1');
const faqs = [
{ id: 'faq1', question: 'What is this component?', answer: 'This is an accordion component built with DaisyUI and Tailwind CSS for creating collapsible content sections.' },
{ id: 'faq2', question: 'How do I use it?', answer: 'Simply import the Accordion component and pass title and children props.' },
{ id: 'faq3', question: 'Can I have multiple open?', answer: 'Yes! By default, accordions can be opened independently.' }
];
return Div({ class: 'flex flex-col gap-2' }, faqs.map(faq =>
Accordion({ Accordion({
name: 'faq-group', title: "Section 2",
title: faq.question,
open: () => openFaq() === faq.id,
children: Div({ class: 'p-2 text-sm' }, faq.answer)
})
));
};
mount(FaqDemo, '#demo-faq');
```
### With Rich Content
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-rich" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Accordion, Div, Span, mount } = window;
const RichDemo = () => {
const open1 = $(true);
const open2 = $(false);
return Div({ class: 'flex flex-col gap-2' }, [
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['📊', 'Statistics']),
open: open1,
children: Div({ class: 'p-2' }, [
Div({ class: 'grid grid-cols-2 gap-4' }, [
Div({ class: 'stat bg-base-100 rounded-lg p-3' }, [
Div({ class: 'stat-title' }, 'Users'),
Div({ class: 'stat-value text-lg' }, '1,234')
]),
Div({ class: 'stat bg-base-100 rounded-lg p-3' }, [
Div({ class: 'stat-title' }, 'Revenue'),
Div({ class: 'stat-value text-lg' }, '$45,678')
])
])
])
}),
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['👥', 'Team Members']),
open: open2, open: open2,
children: Div({ class: 'p-2 space-y-2' }, [ }, div(
Div({ class: 'flex items-center gap-3 p-2 hover:bg-base-100 rounded-lg' }, [ { class: "p-2" },
Div({ class: 'avatar placeholder' }, [ "Content for section 2. You can put any content here.",
Div({ class: 'bg-primary text-primary-content rounded-full w-10 h-10 flex items-center justify-center' }, 'JD') ),),
]),
Div({ class: 'flex-1' }, [
Div({ class: 'font-medium' }, 'John Doe'),
Div({ class: 'text-sm opacity-70' }, 'Developer')
])
])
])
})
]);
};
mount(RichDemo, '#demo-rich');
```
### Form Accordion
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-form" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Accordion, Div, Span, Button, Input, Radio, mount } = window;
const FormAccordion = () => {
const openStep = $('step1');
const formData = $({
name: '',
email: '',
address: '',
payment: 'credit'
});
const updateField = (field, value) => {
formData({ ...formData(), [field]: value });
};
const nextStep = () => {
if (openStep() === 'step1') openStep('step2');
else if (openStep() === 'step2') openStep('step3');
};
const prevStep = () => {
if (openStep() === 'step2') openStep('step1');
else if (openStep() === 'step3') openStep('step2');
};
const handleSubmit = () => {
window.Toast('Form submitted!', 'alert-success', 2000);
};
return Div({ class: 'flex flex-col gap-2' }, [
Accordion({ Accordion({
name: 'form-steps', title: "Section 3",
title: Span({ class: 'flex items-center gap-2' }, ['1⃣', 'Personal Information']),
open: () => openStep() === 'step1',
children: Div({ class: 'p-4 space-y-4' }, [
Input({
label: 'Full Name',
value: () => formData().name,
placeholder: 'Enter your name',
oninput: (e) => updateField('name', e.target.value)
}),
Input({
label: 'Email',
type: 'email',
value: () => formData().email,
placeholder: 'email@example.com',
oninput: (e) => updateField('email', e.target.value)
}),
Div({ class: 'flex justify-end mt-2' }, [
Button({
class: 'btn btn-primary btn-sm',
onclick: nextStep,
disabled: () => !formData().name || !formData().email
}, 'Next →')
])
])
}),
Accordion({
name: 'form-steps',
title: Span({ class: 'flex items-center gap-2' }, ['2⃣', 'Address']),
open: () => openStep() === 'step2',
children: Div({ class: 'p-4 space-y-4' }, [
Input({
label: 'Address',
value: () => formData().address,
placeholder: 'Street address',
oninput: (e) => updateField('address', e.target.value)
}),
Div({ class: 'flex justify-between mt-2' }, [
Button({ class: 'btn btn-ghost btn-sm', onclick: prevStep }, '← Back'),
Button({ class: 'btn btn-primary btn-sm', onclick: nextStep }, 'Next →')
])
])
}),
Accordion({
name: 'form-steps',
title: Span({ class: 'flex items-center gap-2' }, ['3⃣', 'Payment']),
open: () => openStep() === 'step3',
children: Div({ class: 'p-4 space-y-4' }, [
Div({ class: 'flex flex-col gap-2' }, [
Radio({
label: 'Credit Card',
value: () => formData().payment,
radioValue: 'credit',
onclick: () => updateField('payment', 'credit')
}),
Radio({
label: 'PayPal',
value: () => formData().payment,
radioValue: 'paypal',
onclick: () => updateField('payment', 'paypal')
}),
Radio({
label: 'Bank Transfer',
value: () => formData().payment,
radioValue: 'bank',
onclick: () => updateField('payment', 'bank')
})
]),
Div({ class: 'flex justify-between mt-2' }, [
Button({ class: 'btn btn-ghost btn-sm', onclick: prevStep }, '← Back'),
Button({ class: 'btn btn-success btn-sm', onclick: handleSubmit }, 'Submit')
])
])
})
]);
};
mount(FormAccordion, '#demo-form');
```
### All Variants
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Accordion, Div, Span, mount } = window;
const VariantsDemo = () => {
const open1 = $(true);
const open2 = $(false);
const open3 = $(false);
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-sm font-bold' }, 'Default Accordion'),
Accordion({
title: 'Default style',
open: open1,
children: Div({ class: 'p-2' }, 'Default accordion with standard styling.')
}),
Div({ class: 'text-sm font-bold mt-2' }, 'Custom Styling'),
Accordion({
title: Span({ class: 'text-primary font-bold' }, 'Primary Title'),
open: open2,
class: 'bg-primary/5 border-primary/20',
children: Div({ class: 'p-2' }, 'Accordion with custom styling and primary color.')
}),
Div({ class: 'text-sm font-bold mt-2' }, 'With Icons'),
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['✨', 'Featured Content']),
open: open3, open: open3,
children: Div({ class: 'p-2' }, 'Accordion with emoji icons in the title.') children: div(
}) { class: "p-2" },
"Content for section 3. Accordions are great for FAQs.",
),
}),
]); ]);
}; };
mount(VariantsDemo, '#demo-variants'); mount(BasicDemo, "#demo-basic");
``` ```

View File

@@ -39,7 +39,7 @@ Alert supports all **daisyUI Alert classes**:
const { Alert, Div, mount } = window; const { Alert, Div, mount } = window;
const BasicDemo = () => { const BasicDemo = () => {
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Alert({ class: 'alert-info' }, 'This is an informational message.'), Alert({ class: 'alert-info' }, 'This is an informational message.'),
Alert({ class: 'alert-success' }, 'Operation completed successfully!'), Alert({ class: 'alert-success' }, 'Operation completed successfully!'),
Alert({ class: 'alert-warning' }, 'Please review your input before proceeding.'), Alert({ class: 'alert-warning' }, 'Please review your input before proceeding.'),
@@ -62,7 +62,7 @@ mount(BasicDemo, '#demo-basic');
const { Alert, Div, mount } = window; const { Alert, Div, mount } = window;
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Alert({ class: 'alert-info alert-soft' }, 'Soft info alert'), Alert({ class: 'alert-info alert-soft' }, 'Soft info alert'),
Alert({ class: 'alert-info alert-solid' }, 'Solid info alert'), Alert({ class: 'alert-info alert-solid' }, 'Solid info alert'),
Alert({ class: 'alert-success alert-soft' }, 'Soft success alert'), Alert({ class: 'alert-success alert-soft' }, 'Soft success alert'),
@@ -104,14 +104,14 @@ const ActionsDemo = () => {
Toast(`Restored: ${deletedItem()}`, 'alert-success', 2000); Toast(`Restored: ${deletedItem()}`, 'alert-success', 2000);
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex gap-2' }, [ div({ class: 'flex gap-2' }, [
Button({ class: 'btn btn-sm', onclick: () => deleteItem('Document A') }, 'Delete Document A'), button({ class: 'btn btn-sm', onclick: () => deleteItem('Document A') }, 'Delete Document A'),
Button({ class: 'btn btn-sm', onclick: () => deleteItem('Document B') }, 'Delete Document B') button({ class: 'btn btn-sm', onclick: () => deleteItem('Document B') }, 'Delete Document B')
]), ]),
() => showUndo() ? Alert({ class: 'alert-warning alert-soft flex justify-between items-center' }, [ () => showUndo() ? Alert({ class: 'alert-warning alert-soft flex justify-between items-center' }, [
Span({}, `Deleted: ${deletedItem()}`), span({}, `Deleted: ${deletedItem()}`),
Button({ class: 'btn btn-sm btn-primary', onclick: undoDelete }, 'Undo') button({ class: 'btn btn-sm btn-primary', onclick: undoDelete }, 'Undo')
]) : null ]) : null
]); ]);
}; };
@@ -133,12 +133,12 @@ const { Alert, Button, Div, mount } = window;
const DismissibleDemo = () => { const DismissibleDemo = () => {
const visible = $(true); const visible = $(true);
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
() => visible() ? Alert({ class: 'alert-info flex justify-between items-center' }, [ () => visible() ? Alert({ class: 'alert-info flex justify-between items-center' }, [
Span({}, 'This alert can be dismissed. Click the X button to close.'), span({}, 'This alert can be dismissed. Click the X button to close.'),
Button({ class: 'btn btn-xs btn-circle btn-ghost', onclick: () => visible(false) }, '✕') button({ class: 'btn btn-xs btn-circle btn-ghost', onclick: () => visible(false) }, '✕')
]) : null, ]) : null,
() => !visible() ? Button({ class: 'btn btn-sm btn-ghost', onclick: () => visible(true) }, 'Show Alert') : null () => !visible() ? button({ class: 'btn btn-sm btn-ghost', onclick: () => visible(true) }, 'Show Alert') : null
]); ]);
}; };
mount(DismissibleDemo, '#demo-dismissible'); mount(DismissibleDemo, '#demo-dismissible');
@@ -169,8 +169,8 @@ const ReactiveDemo = () => {
} }
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Input({ input({
class: 'input input-bordered', class: 'input input-bordered',
placeholder: 'Enter your email', placeholder: 'Enter your email',
value: email, value: email,
@@ -196,7 +196,7 @@ mount(ReactiveDemo, '#demo-reactive');
const { Alert, Div, mount } = window; const { Alert, Div, mount } = window;
const AllTypesDemo = () => { const AllTypesDemo = () => {
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Alert({ class: 'alert-info' }, ' This is an info alert'), Alert({ class: 'alert-info' }, ' This is an info alert'),
Alert({ class: 'alert-success' }, '✅ This is a success alert'), Alert({ class: 'alert-success' }, '✅ This is a success alert'),
Alert({ class: 'alert-warning' }, '⚠️ This is a warning alert'), Alert({ class: 'alert-warning' }, '⚠️ This is a warning alert'),

View File

@@ -1,276 +1,60 @@
# Autocomplete # Autocomplete
Searchable dropdown with autocomplete functionality, keyboard navigation, and reactive items.
## Tag
`Autocomplete`
## Props
| Prop | Type | Default | Description |
| :------------ | :---------------------------------------------------------- | :------------ | :--------------------------------------- |
| `class` | `string` | `''` | Additional CSS classes for the container |
| `items` | `Array<string \| {value: string, label: string}> \| Signal` | `[]` | Items to search from |
| `value` | `string \| Signal<string>` | `''` | Selected value (reactive) |
| `onselect` | `function(item)` | `-` | Called when an option is selected |
| `label` | `string` | `-` | Label text for the input |
| `placeholder` | `string` | `'Buscar...'` | Placeholder text |
## Styling
Autocomplete wraps a **daisyUI Input component** internally. All Input styling classes work:
| Category | Keywords | Description |
| :------- | :------------------------------------------------------------------------------------------------------------------------------- | :-------------------- |
| Color | `input-primary`, `input-secondary`, `input-accent`, `input-ghost`, `input-info`, `input-success`, `input-warning`, `input-error` | Input color variants |
| Size | `input-xs`, `input-sm`, `input-md`, `input-lg` | Input scale |
| Style | `input-bordered` (default), `input-ghost` | Visual style variants |
> For further details, check the [daisyUI Input Documentation](https://daisyui.com/components/input) Full reference for CSS classes.
## Live Examples
### Basic Autocomplete
<div class="card bg-base-200 border border-base-300 shadow-sm my-6"> <div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body"> <div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3> <h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-basic" class="bg-base-100 p-6 rounded-xl border border-base-300"></div> <div id="app-demo" class="bg-base-100 rounded-xl border border-base-300"></div>
</div> </div>
</div> </div>
```js ```js
const { Autocomplete, mount } = window; const paises = [
"España",
const BasicDemo = () => { "México",
const selected = $(""); "Argentina",
const fruits = [ "Colombia",
"Apple", "Chile",
"Banana", "Perú",
"Orange", "Venezuela",
"Grape", { label: "Estados Unidos", value: "US" },
"Strawberry", { label: "Canadá", value: "CA" },
"Mango", { label: "Reino Unido", value: "UK" },
"Pineapple",
"Watermelon",
]; ];
return Autocomplete({ const App = () => {
items: fruits, const password = $("");
value: selected,
onselect: (value) => selected(value),
});
};
mount(BasicDemo, "#demo-basic");
```
### With Objects // Lógica de validación sencilla
const requirements = [
<div class="card bg-base-200 border border-base-300 shadow-sm my-6"> { label: "Mínimo 8 caracteres", check: () => password().length >= 8 },
<div class="card-body"> { label: "Incluye un número", check: () => /\d/.test(password()) },
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3> { label: "Símbolo especial", check: () => /[^A-Za-z0-9]/.test(password()) }
<div id="demo-objects" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Autocomplete, Div, mount } = window;
const ObjectsDemo = () => {
const selected = $("");
const selectedLabel = $("");
const countries = [
{ value: "mx", label: "Mexico" },
{ value: "us", label: "United States" },
{ value: "ca", label: "Canada" },
{ value: "br", label: "Brazil" },
{ value: "ar", label: "Argentina" },
{ value: "es", label: "Spain" },
]; ];
return Div({ class: "flex flex-col gap-4 w-full" }, [ return div({ class: "p-10 max-w-md" }, [
Autocomplete({ Input({
items: countries, type: "password",
value: selectedLabel, value: password,
onselect: (item) => { class: "input-warning",
const selectedItem = oninput: (e) => password(e.target.value),
typeof item === "string" label: "Pass",
? countries.find((c) => c.label === item) float: true,
: item; left: span({ class: "icon-[lucide--lock] mr-2" }),
selected(selectedItem?.value || ""); // El contenido que se animará con fx() dentro del Input
selectedLabel(selectedItem?.label || ""); content: div({ class: "mt-2 p-4 bg-base-200 rounded-lg shadow-xl border border-base-300" }, [
}, span({ class: "text-xs font-bold uppercase opacity-50" }, "Seguridad:"),
}), ul({ class: "mt-2 space-y-1" },
Div( requirements.map(req => h('li', {
{ class: "alert alert-info mt-4" }, class: () => `flex items-center text-sm ${req.check() ? 'text-success' : 'text-error opacity-50'}`
() => `Selected: ${selected()} - ${selectedLabel()}`, }, [
), span({ class: () => `mr-2 ${req.check() ? 'icon-[lucide--check]' : 'icon-[lucide--x]'}` }),
]); req.label
}; ]))
mount(ObjectsDemo, "#demo-objects");
```
### With Reactive Display
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-reactive" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Autocomplete, Div, mount } = window;
const ReactiveDemo = () => {
const selected = $("");
const programmingLanguages = [
"JavaScript",
"Python",
"Java",
"C++",
"Ruby",
"Go",
"Rust",
"TypeScript",
"Swift",
"Kotlin",
];
return Div({ class: "flex flex-col gap-4 w-full" }, [
Autocomplete({
items: programmingLanguages,
value: selected,
onselect: (value) => selected(value),
}),
() =>
selected()
? Div(
{ class: "alert alert-success mt-4" },
`You selected: ${selected()}`,
) )
: null, ])
})
]); ]);
}; };
mount(ReactiveDemo, "#demo-reactive");
``` mount(App, "#app-demo");
### Dynamic Items
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-dynamic" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Autocomplete, Select, SelectItems, Div, mount } = window;
const DynamicDemo = () => {
const selected = $("");
const filterType = $("all");
const allItems = {
fruits: ["Apple", "Banana", "Orange", "Mango"],
vegetables: ["Carrot", "Broccoli", "Spinach", "Potato"],
all: [
"Apple",
"Banana",
"Orange",
"Mango",
"Carrot",
"Broccoli",
"Spinach",
"Potato",
],
};
const options = [
{ value: "all", label: "All items" },
{ value: "fruits", label: "Fruits" },
{ value: "vegetables", label: "Vegetables" },
];
const handleFilterChange = (e) => {
filterType(e.target.value);
selected("");
setTimeout(() => selected(""), 300);
};
return Div({ class: "flex flex-col gap-4 w-full" }, [
Select(
{
class: "select select-bordered w-full",
value: filterType,
onchange: handleFilterChange,
},
SelectItems({ items: options }),
),
Div({ key: () => filterType() }, [
Autocomplete({
items: () => allItems[filterType()],
value: selected,
onselect: (value) => selected(value),
}),
]),
]);
};
mount(DynamicDemo, "#demo-dynamic");
```
### All Variants
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Autocomplete, Div, mount } = window;
const VariantsDemo = () => {
const colors = [
"Red",
"Blue",
"Green",
"Yellow",
"Purple",
"Orange",
"Pink",
"Brown",
"Black",
"White",
];
return Div({ class: "flex flex-col gap-4" }, [
Div({ class: "font-bold" }, "Primary"),
Autocomplete({
class: "input-primary",
items: colors,
value: $(""),
placeholder: "Search colors...",
}),
Div({ class: "font-bold mt-2" }, "Secondary"),
Autocomplete({
class: "input-secondary",
items: colors,
value: $(""),
placeholder: "Search colors...",
}),
Div({ class: "font-bold mt-2" }, "Ghost"),
Autocomplete({
class: "input-ghost",
items: colors,
value: $(""),
placeholder: "Search colors...",
}),
]);
};
mount(VariantsDemo, "#demo-variants");
``` ```

View File

@@ -45,7 +45,7 @@ Badge({ class: "badge-primary badge-lg" }, "New");
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Div({ class: 'flex flex-wrap gap-2' }, [ return div({ class: 'flex flex-wrap gap-2' }, [
Badge({}, 'Default'), Badge({}, 'Default'),
Badge({ class: 'badge-primary' }, 'Primary'), Badge({ class: 'badge-primary' }, 'Primary'),
Badge({ class: 'badge-secondary' }, 'Secondary'), Badge({ class: 'badge-secondary' }, 'Secondary'),
@@ -70,7 +70,7 @@ mount(BasicDemo, '#demo-basic');
```javascript ```javascript
const SizesDemo = () => { const SizesDemo = () => {
return Div({ class: 'flex flex-wrap gap-2 items-center' }, [ return div({ class: 'flex flex-wrap gap-2 items-center' }, [
Badge({ class: 'badge-xs' }, 'Extra Small'), Badge({ class: 'badge-xs' }, 'Extra Small'),
Badge({ class: 'badge-sm' }, 'Small'), Badge({ class: 'badge-sm' }, 'Small'),
Badge({}, 'Default'), Badge({}, 'Default'),
@@ -92,7 +92,7 @@ mount(SizesDemo, '#demo-sizes');
```javascript ```javascript
const OutlineDemo = () => { const OutlineDemo = () => {
return Div({ class: 'flex flex-wrap gap-2' }, [ return div({ class: 'flex flex-wrap gap-2' }, [
Badge({ class: 'badge-outline' }, 'Default'), Badge({ class: 'badge-outline' }, 'Default'),
Badge({ class: 'badge-outline badge-primary' }, 'Primary'), Badge({ class: 'badge-outline badge-primary' }, 'Primary'),
Badge({ class: 'badge-outline badge-secondary' }, 'Secondary'), Badge({ class: 'badge-outline badge-secondary' }, 'Secondary'),
@@ -117,7 +117,7 @@ mount(OutlineDemo, '#demo-outline');
```javascript ```javascript
const GhostDemo = () => { const GhostDemo = () => {
return Div({ class: 'flex flex-wrap gap-2' }, [ return div({ class: 'flex flex-wrap gap-2' }, [
Badge({ class: 'badge-ghost' }, 'Default'), Badge({ class: 'badge-ghost' }, 'Default'),
Badge({ class: 'badge-ghost badge-primary' }, 'Primary'), Badge({ class: 'badge-ghost badge-primary' }, 'Primary'),
Badge({ class: 'badge-ghost badge-secondary' }, 'Secondary'), Badge({ class: 'badge-ghost badge-secondary' }, 'Secondary'),
@@ -142,26 +142,26 @@ mount(GhostDemo, '#demo-ghost');
```javascript ```javascript
const IconsDemo = () => { const IconsDemo = () => {
return Div({ class: 'flex flex-wrap gap-2' }, [ return div({ class: 'flex flex-wrap gap-2' }, [
Badge({ class: 'gap-1' }, [ Badge({ class: 'gap-1' }, [
Span({}, '✓'), span({}, '✓'),
Span({}, 'Success') span({}, 'Success')
]), ]),
Badge({ class: 'gap-1 badge-warning' }, [ Badge({ class: 'gap-1 badge-warning' }, [
Span({}, '⚠'), span({}, '⚠'),
Span({}, 'Warning') span({}, 'Warning')
]), ]),
Badge({ class: 'gap-1 badge-error' }, [ Badge({ class: 'gap-1 badge-error' }, [
Span({}, '✗'), span({}, '✗'),
Span({}, 'Error') span({}, 'Error')
]), ]),
Badge({ class: 'gap-1 badge-info' }, [ Badge({ class: 'gap-1 badge-info' }, [
Span({}, ''), span({}, ''),
Span({}, 'Info') span({}, 'Info')
]), ]),
Badge({ class: 'gap-1' }, [ Badge({ class: 'gap-1' }, [
Span({}, '★'), span({}, '★'),
Span({}, '4.5') span({}, '4.5')
]) ])
]); ]);
}; };
@@ -187,9 +187,9 @@ const StatusDemo = () => {
{ label: 'Archived', class: 'badge-ghost' } { label: 'Archived', class: 'badge-ghost' }
]; ];
return Div({ class: 'flex flex-col gap-2' }, [ return div({ class: 'flex flex-col gap-2' }, [
Div({ class: 'text-sm font-bold mb-2' }, 'Order Status'), div({ class: 'text-sm font-bold mb-2' }, 'Order Status'),
Div({ class: 'flex flex-wrap gap-2' }, statuses.map(status => div({ class: 'flex flex-wrap gap-2' }, statuses.map(status =>
Badge({ class: status.class }, status.label) Badge({ class: status.class }, status.label)
)) ))
]); ]);
@@ -212,17 +212,17 @@ const CountDemo = () => {
const messages = $(5); const messages = $(5);
const updates = $(0); const updates = $(0);
return Div({ class: 'flex flex-wrap gap-6' }, [ return div({ class: 'flex flex-wrap gap-6' }, [
Div({ class: 'flex items-center gap-2' }, [ div({ class: 'flex items-center gap-2' }, [
Span({}, 'Notifications'), span({}, 'Notifications'),
Badge({ class: 'badge-primary' }, () => notifications()) Badge({ class: 'badge-primary' }, () => notifications())
]), ]),
Div({ class: 'flex items-center gap-2' }, [ div({ class: 'flex items-center gap-2' }, [
Span({}, 'Messages'), span({}, 'Messages'),
Badge({ class: 'badge-secondary' }, () => messages()) Badge({ class: 'badge-secondary' }, () => messages())
]), ]),
Div({ class: 'flex items-center gap-2' }, [ div({ class: 'flex items-center gap-2' }, [
Span({}, 'Updates'), span({}, 'Updates'),
Badge({ class: 'badge-ghost' }, () => updates() || '0') Badge({ class: 'badge-ghost' }, () => updates() || '0')
]) ])
]); ]);
@@ -243,13 +243,13 @@ mount(CountDemo, '#demo-count');
const InteractiveDemo = () => { const InteractiveDemo = () => {
const count = $(0); const count = $(0);
return Div({ class: 'flex flex-col gap-4 items-center' }, [ return div({ class: 'flex flex-col gap-4 items-center' }, [
Div({ class: 'flex items-center gap-4' }, [ div({ class: 'flex items-center gap-4' }, [
Button({ class: 'btn btn-sm', onclick: () => count(count() - 1) }, '-'), button({ class: 'btn btn-sm', onclick: () => count(count() - 1) }, '-'),
Badge({ class: 'badge-primary text-lg min-w-[4rem] justify-center' }, () => count()), Badge({ class: 'badge-primary text-lg min-w-[4rem] justify-center' }, () => count()),
Button({ class: 'btn btn-sm', onclick: () => count(count() + 1) }, '+') button({ class: 'btn btn-sm', onclick: () => count(count() + 1) }, '+')
]), ]),
Button({ button({
class: 'btn btn-ghost btn-sm', class: 'btn btn-ghost btn-sm',
onclick: () => count(0) onclick: () => count(0)
}, 'Reset') }, 'Reset')
@@ -269,19 +269,19 @@ mount(InteractiveDemo, '#demo-interactive');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'flex flex-col gap-6' }, [ return div({ class: 'flex flex-col gap-6' }, [
Div({ class: 'flex flex-wrap gap-2' }, [ div({ class: 'flex flex-wrap gap-2' }, [
Badge({ class: 'badge-xs' }, 'XS'), Badge({ class: 'badge-xs' }, 'XS'),
Badge({ class: 'badge-sm' }, 'SM'), Badge({ class: 'badge-sm' }, 'SM'),
Badge({}, 'MD'), Badge({}, 'MD'),
Badge({ class: 'badge-lg' }, 'LG') Badge({ class: 'badge-lg' }, 'LG')
]), ]),
Div({ class: 'flex flex-wrap gap-2' }, [ div({ class: 'flex flex-wrap gap-2' }, [
Badge({ class: 'badge-primary badge-sm' }, 'Primary'), Badge({ class: 'badge-primary badge-sm' }, 'Primary'),
Badge({ class: 'badge-secondary badge-sm' }, 'Secondary'), Badge({ class: 'badge-secondary badge-sm' }, 'Secondary'),
Badge({ class: 'badge-accent badge-sm' }, 'Accent') Badge({ class: 'badge-accent badge-sm' }, 'Accent')
]), ]),
Div({ class: 'flex flex-wrap gap-2' }, [ div({ class: 'flex flex-wrap gap-2' }, [
Badge({ class: 'badge-outline badge-primary' }, 'Outline'), Badge({ class: 'badge-outline badge-primary' }, 'Outline'),
Badge({ class: 'badge-ghost badge-primary' }, 'Ghost') Badge({ class: 'badge-ghost badge-primary' }, 'Ghost')
]) ])
@@ -301,18 +301,18 @@ mount(VariantsDemo, '#demo-variants');
```javascript ```javascript
const InlineDemo = () => { const InlineDemo = () => {
return Div({ class: 'space-y-2' }, [ return div({ class: 'space-y-2' }, [
Div({ class: 'text-sm' }, [ div({ class: 'text-sm' }, [
'Your order is ', 'Your order is ',
Badge({ class: 'badge-success badge-sm' }, 'Confirmed'), Badge({ class: 'badge-success badge-sm' }, 'Confirmed'),
' and will be shipped soon.' ' and will be shipped soon.'
]), ]),
Div({ class: 'text-sm' }, [ div({ class: 'text-sm' }, [
'This feature is ', 'This feature is ',
Badge({ class: 'badge-warning badge-sm' }, 'Beta'), Badge({ class: 'badge-warning badge-sm' }, 'Beta'),
' and may change.' ' and may change.'
]), ]),
Div({ class: 'text-sm' }, [ div({ class: 'text-sm' }, [
'Version ', 'Version ',
Badge({ class: 'badge-info badge-xs' }, 'v2.1.0'), Badge({ class: 'badge-info badge-xs' }, 'v2.1.0'),
' released on March 2026' ' released on March 2026'

View File

@@ -31,7 +31,7 @@
### Example ### Example
```javascript ```javascript
Button({ class: "btn-primary btn-lg btn-circle gap-4" }, "Click Me"); button({ class: "btn-primary btn-lg btn-circle gap-4" }, "Click Me");
// Applies: primary color, large size, circular shape // Applies: primary color, large size, circular shape
// class is any css class from pure css or favorite framework // class is any css class from pure css or favorite framework
``` ```
@@ -46,7 +46,7 @@ Button({ class: "btn-primary btn-lg btn-circle gap-4" }, "Click Me");
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Button({ class: "btn-primary" }, "Click Me"); return button({ class: "btn-primary" }, "Click Me");
}; };
mount(BasicDemo, "#demo-basic"); mount(BasicDemo, "#demo-basic");
``` ```
@@ -59,7 +59,7 @@ mount(BasicDemo, "#demo-basic");
const LoadingDemo = () => { const LoadingDemo = () => {
const isSaving = $(false); const isSaving = $(false);
return Button( return button(
{ {
class: "btn-success", class: "btn-success",
disabled: isSaving, disabled: isSaving,
@@ -81,8 +81,8 @@ mount(LoadingDemo, "#demo-loading");
```javascript ```javascript
const IconDemo = () => { const IconDemo = () => {
return Div({ class: "flex flex-wrap gap-2 justify-center" }, [ return div({ class: "flex flex-wrap gap-2 justify-center" }, [
Button({ class: "btn-primary" }, [Icon("icon-[lucide--x]"), "Favorite"]), button({ class: "btn-primary" }, [Icon("icon-[lucide--x]"), "Favorite"]),
]); ]);
}; };
mount(IconDemo, "#demo-icon"); mount(IconDemo, "#demo-icon");
@@ -96,7 +96,7 @@ mount(IconDemo, "#demo-icon");
const BadgeDemo = () => { const BadgeDemo = () => {
return Indicator( return Indicator(
{ value: "3", class: "badge-accent" }, { value: "3", class: "badge-accent" },
Button({ class: "btn-outline" }, "Notifications"), button({ class: "btn-outline" }, "Notifications"),
); );
}; };
mount(BadgeDemo, "#demo-badge"); mount(BadgeDemo, "#demo-badge");
@@ -110,7 +110,7 @@ mount(BadgeDemo, "#demo-badge");
const TooltipDemo = () => { const TooltipDemo = () => {
return Tooltip( return Tooltip(
{ tip: "Delete item" }, { tip: "Delete item" },
Button({ class: "btn-ghost" }, "Delete"), button({ class: "btn-ghost" }, "Delete"),
); );
}; };
mount(TooltipDemo, "#demo-tooltip"); mount(TooltipDemo, "#demo-tooltip");
@@ -127,7 +127,7 @@ const CombinedDemo = () => {
{ tip: () => `${count()} likes` }, { tip: () => `${count()} likes` },
Indicator( Indicator(
{ value: count, class: "badge-accent" }, { value: count, class: "badge-accent" },
Button( button(
{ {
class: "btn-primary btn-lg", class: "btn-primary btn-lg",
onclick: () => count(count() + 1), onclick: () => count(count() + 1),
@@ -146,13 +146,13 @@ mount(CombinedDemo, "#demo-combined");
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: "flex flex-wrap gap-2 justify-center" }, [ return div({ class: "flex flex-wrap gap-2 justify-center" }, [
Button({ class: "btn-primary" }, "Primary"), button({ class: "btn-primary" }, "Primary"),
Button({ class: "btn-secondary" }, "Secondary"), button({ class: "btn-secondary" }, "Secondary"),
Button({ class: "btn-accent" }, "Accent"), button({ class: "btn-accent" }, "Accent"),
Button({ class: "btn-ghost" }, "Ghost"), button({ class: "btn-ghost" }, "Ghost"),
Button({ class: "btn-outline" }, "Outline"), button({ class: "btn-outline" }, "Outline"),
Button({ class: "btn-disabled" }, "Disabled"), button({ class: "btn-disabled" }, "Disabled"),
]); ]);
}; };
mount(VariantsDemo, "#demo-variants"); mount(VariantsDemo, "#demo-variants");

View File

@@ -77,7 +77,7 @@ mount(BasicDemo, '#demo-basic');
const ToggleDemo = () => { const ToggleDemo = () => {
const enabled = $(false); const enabled = $(false);
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Checkbox({ Checkbox({
label: 'Enable notifications', label: 'Enable notifications',
value: enabled, value: enabled,
@@ -85,8 +85,8 @@ const ToggleDemo = () => {
onclick: () => enabled(!enabled()) onclick: () => enabled(!enabled())
}), }),
() => enabled() () => enabled()
? Div({ class: 'alert alert-success' }, 'Notifications are ON') ? div({ class: 'alert alert-success' }, 'Notifications are ON')
: Div({ class: 'alert alert-soft' }, 'Notifications are OFF') : div({ class: 'alert alert-soft' }, 'Notifications are OFF')
]); ]);
}; };
mount(ToggleDemo, '#demo-toggle'); mount(ToggleDemo, '#demo-toggle');
@@ -103,7 +103,7 @@ mount(ToggleDemo, '#demo-toggle');
```javascript ```javascript
const DisabledDemo = () => { const DisabledDemo = () => {
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Checkbox({ Checkbox({
label: 'Checked and disabled', label: 'Checked and disabled',
value: true, value: true,
@@ -148,13 +148,13 @@ const MultipleDemo = () => {
selectAll(allSelected); selectAll(allSelected);
}; };
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Checkbox({ Checkbox({
label: 'Select all', label: 'Select all',
value: selectAll, value: selectAll,
onclick: () => toggleAll(!selectAll()) onclick: () => toggleAll(!selectAll())
}), }),
Div({ class: 'divider my-1' }), div({ class: 'divider my-1' }),
...options.map(opt => Checkbox({ ...options.map(opt => Checkbox({
label: opt.label, label: opt.label,
value: opt.selected, value: opt.selected,
@@ -163,7 +163,7 @@ const MultipleDemo = () => {
updateSelectAll(); updateSelectAll();
} }
})), })),
Div({ class: 'mt-2 text-sm opacity-70' }, () => { div({ class: 'mt-2 text-sm opacity-70' }, () => {
const count = options.filter(opt => opt.selected()).length; const count = options.filter(opt => opt.selected()).length;
return `${count} of ${options.length} selected`; return `${count} of ${options.length} selected`;
}) })
@@ -213,8 +213,8 @@ const VariantsDemo = () => {
const variant2 = $(false); const variant2 = $(false);
const variant3 = $(true); const variant3 = $(true);
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Div({ class: 'flex items-center gap-4' }, [ div({ class: 'flex items-center gap-4' }, [
Checkbox({ Checkbox({
label: 'Primary', label: 'Primary',
value: variant1, value: variant1,
@@ -228,7 +228,7 @@ const VariantsDemo = () => {
onclick: () => variant2(!variant2()) onclick: () => variant2(!variant2())
}) })
]), ]),
Div({ class: 'flex items-center gap-4' }, [ div({ class: 'flex items-center gap-4' }, [
Checkbox({ Checkbox({
label: 'Accent', label: 'Accent',
value: variant3, value: variant3,
@@ -262,14 +262,14 @@ const FormDemo = () => {
const weekly = $(false); const weekly = $(false);
const monthly = $(true); const monthly = $(true);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-sm font-bold' }, 'Newsletter preferences'), div({ class: 'text-sm font-bold' }, 'Newsletter preferences'),
Checkbox({ Checkbox({
label: 'Subscribe to newsletter', label: 'Subscribe to newsletter',
value: subscribe, value: subscribe,
onclick: () => subscribe(!subscribe()) onclick: () => subscribe(!subscribe())
}), }),
() => subscribe() ? Div({ class: 'ml-6 flex flex-col gap-2' }, [ () => subscribe() ? div({ class: 'ml-6 flex flex-col gap-2' }, [
Checkbox({ Checkbox({
label: 'Weekly updates', label: 'Weekly updates',
value: weekly, value: weekly,
@@ -282,9 +282,9 @@ const FormDemo = () => {
}) })
]) : null, ]) : null,
() => subscribe() && (weekly() || monthly()) () => subscribe() && (weekly() || monthly())
? Div({ class: 'alert alert-success text-sm mt-2' }, 'You will receive updates!') ? div({ class: 'alert alert-success text-sm mt-2' }, 'You will receive updates!')
: subscribe() : subscribe()
? Div({ class: 'alert alert-warning text-sm mt-2' }, 'Select at least one frequency') ? div({ class: 'alert alert-warning text-sm mt-2' }, 'Select at least one frequency')
: null : null
]); ]);
}; };

View File

@@ -61,16 +61,16 @@ mount(BasicDemo, '#demo-basic');
const PreviewDemo = () => { const PreviewDemo = () => {
const color = $('#10b981'); const color = $('#10b981');
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Colorpicker({ Colorpicker({
label: 'Choose color', label: 'Choose color',
value: color value: color
}), }),
Div({ div({
class: 'w-full h-20 rounded-lg shadow-inner transition-all duration-200 flex items-center justify-center', class: 'w-full h-20 rounded-lg shadow-inner transition-all duration-200 flex items-center justify-center',
style: () => `background-color: ${color()}` style: () => `background-color: ${color()}`
}, [ }, [
Div({ class: 'text-center font-mono text-sm bg-black/20 px-2 py-1 rounded' }, () => color()) div({ class: 'text-center font-mono text-sm bg-black/20 px-2 py-1 rounded' }, () => color())
]) ])
]); ]);
}; };
@@ -96,20 +96,20 @@ const PaletteDemo = () => {
'#ec489a', '#f43f5e', '#6b7280', '#1f2937' '#ec489a', '#f43f5e', '#6b7280', '#1f2937'
]; ];
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Colorpicker({ Colorpicker({
label: 'Custom color', label: 'Custom color',
value: selectedColor value: selectedColor
}), }),
Div({ class: 'divider text-xs' }, 'Or choose from palette'), div({ class: 'divider text-xs' }, 'Or choose from palette'),
Div({ class: 'grid grid-cols-8 gap-2' }, presets.map(color => div({ class: 'grid grid-cols-8 gap-2' }, presets.map(color =>
Button({ button({
class: `w-8 h-8 rounded-lg shadow-sm transition-transform hover:scale-110`, class: `w-8 h-8 rounded-lg shadow-sm transition-transform hover:scale-110`,
style: `background-color: ${color}`, style: `background-color: ${color}`,
onclick: () => selectedColor(color) onclick: () => selectedColor(color)
}) })
)), )),
Div({ class: 'mt-2 text-center text-sm font-mono' }, () => selectedColor()) div({ class: 'mt-2 text-center text-sm font-mono' }, () => selectedColor())
]); ]);
}; };
mount(PaletteDemo, '#demo-palette'); mount(PaletteDemo, '#demo-palette');
@@ -129,8 +129,8 @@ const TextDemo = () => {
const bgColor = $('#1e293b'); const bgColor = $('#1e293b');
const textColor = $('#f8fafc'); const textColor = $('#f8fafc');
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Div({ class: 'flex gap-4' }, [ div({ class: 'flex gap-4' }, [
Colorpicker({ Colorpicker({
label: 'Background', label: 'Background',
value: bgColor value: bgColor
@@ -140,7 +140,7 @@ const TextDemo = () => {
value: textColor value: textColor
}) })
]), ]),
Div({ div({
class: 'p-6 rounded-lg text-center font-bold transition-all duration-200', class: 'p-6 rounded-lg text-center font-bold transition-all duration-200',
style: () => `background-color: ${bgColor()}; color: ${textColor()}` style: () => `background-color: ${bgColor()}; color: ${textColor()}`
}, [ }, [
@@ -162,7 +162,7 @@ mount(TextDemo, '#demo-text');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'flex flex-wrap gap-4 items-center' }, [ return div({ class: 'flex flex-wrap gap-4 items-center' }, [
Colorpicker({ Colorpicker({
label: 'Primary', label: 'Primary',
value: $('#3b82f6') value: $('#3b82f6')
@@ -199,22 +199,22 @@ const DynamicDemo = () => {
const secondary = $('#ef4444'); const secondary = $('#ef4444');
const accent = $('#10b981'); const accent = $('#10b981');
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Div({ class: 'flex flex-wrap gap-4' }, [ div({ class: 'flex flex-wrap gap-4' }, [
Colorpicker({ label: 'Primary', value: primary }), Colorpicker({ label: 'Primary', value: primary }),
Colorpicker({ label: 'Secondary', value: secondary }), Colorpicker({ label: 'Secondary', value: secondary }),
Colorpicker({ label: 'Accent', value: accent }) Colorpicker({ label: 'Accent', value: accent })
]), ]),
Div({ class: 'grid grid-cols-3 gap-2 mt-2' }, [ div({ class: 'grid grid-cols-3 gap-2 mt-2' }, [
Div({ div({
class: 'h-12 rounded-lg shadow-sm flex items-center justify-center text-xs font-bold text-white', class: 'h-12 rounded-lg shadow-sm flex items-center justify-center text-xs font-bold text-white',
style: () => `background-color: ${primary()}` style: () => `background-color: ${primary()}`
}, 'Primary'), }, 'Primary'),
Div({ div({
class: 'h-12 rounded-lg shadow-sm flex items-center justify-center text-xs font-bold text-white', class: 'h-12 rounded-lg shadow-sm flex items-center justify-center text-xs font-bold text-white',
style: () => `background-color: ${secondary()}` style: () => `background-color: ${secondary()}`
}, 'Secondary'), }, 'Secondary'),
Div({ div({
class: 'h-12 rounded-lg shadow-sm flex items-center justify-center text-xs font-bold text-white', class: 'h-12 rounded-lg shadow-sm flex items-center justify-center text-xs font-bold text-white',
style: () => `background-color: ${accent()}` style: () => `background-color: ${accent()}`
}, 'Accent') }, 'Accent')

View File

@@ -40,7 +40,7 @@ Datepicker wraps a **daisyUI Input component** internally. All Input styling cla
</div> </div>
</div> </div>
```javascript ```js
const BasicDemo = () => { const BasicDemo = () => {
const date = $(''); const date = $('');
@@ -66,14 +66,14 @@ mount(BasicDemo, '#demo-basic');
const RangeDemo = () => { const RangeDemo = () => {
const range = $({ start: '', end: '' }); const range = $({ start: '', end: '' });
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Datepicker({ Datepicker({
label: 'Date range', label: 'Date range',
value: range, value: range,
range: true, range: true,
placeholder: 'Select start and end date...' placeholder: 'Select start and end date...'
}), }),
() => range().start && range().end ? Div({ class: 'alert alert-success' }, [ () => range().start && range().end ? div({ class: 'alert alert-success' }, [
`Selected: ${range().start}${range().end}` `Selected: ${range().start}${range().end}`
]) : null ]) : null
]); ]);
@@ -94,14 +94,14 @@ mount(RangeDemo, '#demo-range');
const TimeDemo = () => { const TimeDemo = () => {
const datetime = $(''); const datetime = $('');
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Datepicker({ Datepicker({
label: 'Select date and time', label: 'Select date and time',
value: datetime, value: datetime,
hour: true, hour: true,
placeholder: 'Choose date and time...' placeholder: 'Choose date and time...'
}), }),
() => datetime() ? Div({ class: 'alert alert-info' }, [ () => datetime() ? div({ class: 'alert alert-info' }, [
`Selected: ${datetime()}` `Selected: ${datetime()}`
]) : null ]) : null
]); ]);
@@ -122,7 +122,7 @@ mount(TimeDemo, '#demo-time');
const RangeTimeDemo = () => { const RangeTimeDemo = () => {
const range = $({ start: '', end: '', startHour: 9, endHour: 17 }); const range = $({ start: '', end: '', startHour: 9, endHour: 17 });
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Datepicker({ Datepicker({
label: 'Schedule range', label: 'Schedule range',
value: range, value: range,
@@ -130,7 +130,7 @@ const RangeTimeDemo = () => {
hour: true, hour: true,
placeholder: 'Select date and time range...' placeholder: 'Select date and time range...'
}), }),
() => range().start && range().end ? Div({ class: 'alert alert-primary' }, [ () => range().start && range().end ? div({ class: 'alert alert-primary' }, [
`From ${range().start} ${range().startHour || 9}:00 to ${range().end} ${range().endHour || 17}:00` `From ${range().start} ${range().startHour || 9}:00 to ${range().end} ${range().endHour || 17}:00`
]) : null ]) : null
]); ]);
@@ -152,17 +152,17 @@ const ReactiveDemo = () => {
const date = $(''); const date = $('');
const today = new Date().toISOString().split('T')[0]; const today = new Date().toISOString().split('T')[0];
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Datepicker({ Datepicker({
label: 'Select date', label: 'Select date',
value: date, value: date,
placeholder: 'Choose a date...' placeholder: 'Choose a date...'
}), }),
Div({ class: 'stats shadow' }, [ div({ class: 'stats shadow' }, [
Div({ class: 'stat' }, [ div({ class: 'stat' }, [
Div({ class: 'stat-title' }, 'Selected date'), div({ class: 'stat-title' }, 'Selected date'),
Div({ class: 'stat-value text-sm' }, () => date() || 'Not selected'), div({ class: 'stat-value text-sm' }, () => date() || 'Not selected'),
Div({ class: 'stat-desc' }, () => date() === today ? 'Today' : '') div({ class: 'stat-desc' }, () => date() === today ? 'Today' : '')
]) ])
]) ])
]); ]);
@@ -181,7 +181,7 @@ mount(ReactiveDemo, '#demo-reactive');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Datepicker({ Datepicker({
label: 'Single date', label: 'Single date',
value: $('2024-12-25'), value: $('2024-12-25'),

View File

@@ -45,16 +45,16 @@ const BasicDemo = () => {
return Drawer({ return Drawer({
id: 'basic-drawer', id: 'basic-drawer',
open: isOpen, open: isOpen,
side: Div({ class: 'p-4' }, [ side: div({ class: 'p-4' }, [
Div({ class: 'text-lg font-bold mb-4' }, 'Menu'), div({ class: 'text-lg font-bold mb-4' }, 'Menu'),
Div({ class: 'flex flex-col gap-2' }, [ div({ class: 'flex flex-col gap-2' }, [
Button({ class: 'btn btn-ghost justify-start' }, 'Home'), button({ class: 'btn btn-ghost justify-start' }, 'Home'),
Button({ class: 'btn btn-ghost justify-start' }, 'About'), button({ class: 'btn btn-ghost justify-start' }, 'About'),
Button({ class: 'btn btn-ghost justify-start' }, 'Contact') button({ class: 'btn btn-ghost justify-start' }, 'Contact')
]) ])
]), ]),
content: Div({ class: 'p-4 text-center' }, [ content: div({ class: 'p-4 text-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, 'Open Drawer') }, 'Open Drawer')
@@ -88,31 +88,31 @@ const NavDrawer = () => {
return Drawer({ return Drawer({
id: 'nav-drawer', id: 'nav-drawer',
open: isOpen, open: isOpen,
side: Div({ class: 'p-4 w-64' }, [ side: div({ class: 'p-4 w-64' }, [
Div({ class: 'text-xl font-bold mb-6' }, 'MyApp'), div({ class: 'text-xl font-bold mb-6' }, 'MyApp'),
Div({ class: 'flex flex-col gap-1' }, [ div({ class: 'flex flex-col gap-1' }, [
Button({ button({
class: `btn btn-ghost justify-start ${activePage() === 'home' ? 'btn-active' : ''}`, class: `btn btn-ghost justify-start ${activePage() === 'home' ? 'btn-active' : ''}`,
onclick: () => { onclick: () => {
activePage('home'); activePage('home');
isOpen(false); isOpen(false);
} }
}, '🏠 Home'), }, '🏠 Home'),
Button({ button({
class: `btn btn-ghost justify-start ${activePage() === 'about' ? 'btn-active' : ''}`, class: `btn btn-ghost justify-start ${activePage() === 'about' ? 'btn-active' : ''}`,
onclick: () => { onclick: () => {
activePage('about'); activePage('about');
isOpen(false); isOpen(false);
} }
}, ' About'), }, ' About'),
Button({ button({
class: `btn btn-ghost justify-start ${activePage() === 'services' ? 'btn-active' : ''}`, class: `btn btn-ghost justify-start ${activePage() === 'services' ? 'btn-active' : ''}`,
onclick: () => { onclick: () => {
activePage('services'); activePage('services');
isOpen(false); isOpen(false);
} }
}, '⚙️ Services'), }, '⚙️ Services'),
Button({ button({
class: `btn btn-ghost justify-start ${activePage() === 'contact' ? 'btn-active' : ''}`, class: `btn btn-ghost justify-start ${activePage() === 'contact' ? 'btn-active' : ''}`,
onclick: () => { onclick: () => {
activePage('contact'); activePage('contact');
@@ -121,18 +121,18 @@ const NavDrawer = () => {
}, '📧 Contact') }, '📧 Contact')
]) ])
]), ]),
content: Div({ class: 'p-4' }, [ content: div({ class: 'p-4' }, [
Div({ class: 'flex justify-between items-center mb-4' }, [ div({ class: 'flex justify-between items-center mb-4' }, [
Button({ button({
class: 'btn btn-ghost btn-circle', class: 'btn btn-ghost btn-circle',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, '☰'), }, '☰'),
Span({ class: 'text-lg font-bold' }, 'MyApp') span({ class: 'text-lg font-bold' }, 'MyApp')
]), ]),
Div({ class: 'card bg-base-200 shadow-lg' }, [ div({ class: 'card bg-base-200 shadow-lg' }, [
Div({ class: 'card-body' }, [ div({ class: 'card-body' }, [
Div({ class: 'text-2xl font-bold mb-2' }, () => activePage().charAt(0).toUpperCase() + activePage().slice(1)), div({ class: 'text-2xl font-bold mb-2' }, () => activePage().charAt(0).toUpperCase() + activePage().slice(1)),
Div({ class: 'text-lg' }, () => pages[activePage()]) div({ class: 'text-lg' }, () => pages[activePage()])
]) ])
]) ])
]) ])
@@ -160,17 +160,17 @@ const SettingsDrawer = () => {
return Drawer({ return Drawer({
id: 'settings-drawer', id: 'settings-drawer',
open: isOpen, open: isOpen,
side: Div({ class: 'p-4 w-80' }, [ side: div({ class: 'p-4 w-80' }, [
Div({ class: 'flex justify-between items-center mb-6' }, [ div({ class: 'flex justify-between items-center mb-6' }, [
Span({ class: 'text-xl font-bold' }, 'Settings'), span({ class: 'text-xl font-bold' }, 'Settings'),
Button({ button({
class: 'btn btn-ghost btn-circle btn-sm', class: 'btn btn-ghost btn-circle btn-sm',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, '✕') }, '✕')
]), ]),
Div({ class: 'flex flex-col gap-4' }, [ div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({}, 'Dark Mode'), span({}, 'Dark Mode'),
Swap({ Swap({
value: darkMode, value: darkMode,
on: "🌙", on: "🌙",
@@ -178,8 +178,8 @@ const SettingsDrawer = () => {
onclick: () => darkMode(!darkMode()) onclick: () => darkMode(!darkMode())
}) })
]), ]),
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({}, 'Notifications'), span({}, 'Notifications'),
Swap({ Swap({
value: notifications, value: notifications,
on: "🔔", on: "🔔",
@@ -187,8 +187,8 @@ const SettingsDrawer = () => {
onclick: () => notifications(!notifications()) onclick: () => notifications(!notifications())
}) })
]), ]),
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({}, 'Auto Save'), span({}, 'Auto Save'),
Swap({ Swap({
value: autoSave, value: autoSave,
on: "✅", on: "✅",
@@ -197,37 +197,37 @@ const SettingsDrawer = () => {
}) })
]) ])
]), ]),
Div({ class: 'divider my-4' }), div({ class: 'divider my-4' }),
Div({ class: 'flex gap-2' }, [ div({ class: 'flex gap-2' }, [
Button({ button({
class: 'btn btn-primary flex-1', class: 'btn btn-primary flex-1',
onclick: () => { onclick: () => {
isOpen(false); isOpen(false);
Toast('Settings saved!', 'alert-success', 2000); Toast('Settings saved!', 'alert-success', 2000);
} }
}, 'Save'), }, 'Save'),
Button({ button({
class: 'btn btn-ghost flex-1', class: 'btn btn-ghost flex-1',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, 'Cancel') }, 'Cancel')
]) ])
]), ]),
content: Div({ class: 'p-4' }, [ content: div({ class: 'p-4' }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({ class: 'text-lg font-bold' }, 'Dashboard'), span({ class: 'text-lg font-bold' }, 'Dashboard'),
Button({ button({
class: 'btn btn-ghost btn-circle', class: 'btn btn-ghost btn-circle',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, '⚙️') }, '⚙️')
]), ]),
Div({ class: 'mt-4 grid grid-cols-2 gap-4' }, [ div({ class: 'mt-4 grid grid-cols-2 gap-4' }, [
Div({ class: 'stat bg-base-200 rounded-lg p-4' }, [ div({ class: 'stat bg-base-200 rounded-lg p-4' }, [
Div({ class: 'stat-title' }, 'Users'), div({ class: 'stat-title' }, 'Users'),
Div({ class: 'stat-value' }, '1,234') div({ class: 'stat-value' }, '1,234')
]), ]),
Div({ class: 'stat bg-base-200 rounded-lg p-4' }, [ div({ class: 'stat bg-base-200 rounded-lg p-4' }, [
Div({ class: 'stat-title' }, 'Revenue'), div({ class: 'stat-title' }, 'Revenue'),
Div({ class: 'stat-value' }, '$45K') div({ class: 'stat-value' }, '$45K')
]) ])
]) ])
]) ])
@@ -268,70 +268,70 @@ const CartDrawer = () => {
return Drawer({ return Drawer({
id: 'cart-drawer', id: 'cart-drawer',
open: isOpen, open: isOpen,
side: Div({ class: 'flex flex-col h-full' }, [ side: div({ class: 'flex flex-col h-full' }, [
Div({ class: 'p-4 border-b border-base-300' }, [ div({ class: 'p-4 border-b border-base-300' }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({ class: 'text-xl font-bold' }, `Cart (${cart().length} items)`), span({ class: 'text-xl font-bold' }, `Cart (${cart().length} items)`),
Button({ button({
class: 'btn btn-ghost btn-circle btn-sm', class: 'btn btn-ghost btn-circle btn-sm',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, Span('✕')) }, span('✕'))
]) ])
]), ]),
Div({ class: 'flex-1 overflow-y-auto p-4' }, cart().length === 0 div({ class: 'flex-1 overflow-y-auto p-4' }, cart().length === 0
? Div({ class: 'text-center text-gray-500 mt-8' }, 'Your cart is empty') ? div({ class: 'text-center text-gray-500 mt-8' }, 'Your cart is empty')
: Div({ class: 'flex flex-col gap-3' }, cart().map(item => : div({ class: 'flex flex-col gap-3' }, cart().map(item =>
Div({ class: 'flex gap-3 items-center p-2 bg-base-200 rounded-lg' }, [ div({ class: 'flex gap-3 items-center p-2 bg-base-200 rounded-lg' }, [
Div({ class: 'flex-1' }, [ div({ class: 'flex-1' }, [
Div({ class: 'font-medium' }, item.name), div({ class: 'font-medium' }, item.name),
Div({ class: 'text-sm' }, `$${item.price} each`) div({ class: 'text-sm' }, `$${item.price} each`)
]), ]),
Div({ class: 'flex items-center gap-2' }, [ div({ class: 'flex items-center gap-2' }, [
Button({ button({
class: 'btn btn-xs btn-circle', class: 'btn btn-xs btn-circle',
onclick: () => updateQuantity(item.id, -1) onclick: () => updateQuantity(item.id, -1)
}, Span('-')), }, span('-')),
Span({ class: 'w-8 text-center' }, item.quantity), span({ class: 'w-8 text-center' }, item.quantity),
Button({ button({
class: 'btn btn-xs btn-circle', class: 'btn btn-xs btn-circle',
onclick: () => updateQuantity(item.id, 1) onclick: () => updateQuantity(item.id, 1)
}, Span('+')) }, span('+'))
]), ]),
Span({ class: 'font-bold w-16 text-right' }, `$${item.price * item.quantity}`) span({ class: 'font-bold w-16 text-right' }, `$${item.price * item.quantity}`)
]) ])
)) ))
), ),
Div({ class: 'p-4 border-t border-base-300' }, [ div({ class: 'p-4 border-t border-base-300' }, [
Div({ class: 'flex justify-between items-center mb-4' }, [ div({ class: 'flex justify-between items-center mb-4' }, [
Span({ class: 'font-bold' }, 'Total'), span({ class: 'font-bold' }, 'Total'),
Span({ class: 'text-xl font-bold' }, () => `$${total()}`) span({ class: 'text-xl font-bold' }, () => `$${total()}`)
]), ]),
Button({ button({
class: 'btn btn-primary w-full', class: 'btn btn-primary w-full',
onclick: () => { onclick: () => {
isOpen(false); isOpen(false);
Toast('Checkout initiated!', 'alert-success', 2000); Toast('Checkout initiated!', 'alert-success', 2000);
}, },
disabled: () => cart().length === 0 disabled: () => cart().length === 0
}, Span('Checkout')) }, span('Checkout'))
]) ])
]), ]),
content: Div({ class: 'p-4' }, [ content: div({ class: 'p-4' }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({ class: 'text-lg font-bold' }, 'Store'), span({ class: 'text-lg font-bold' }, 'Store'),
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, Span({ class: 'flex items-center gap-2' }, [Span('🛒'), Span(`Cart (${cart().length})`)])) }, span({ class: 'flex items-center gap-2' }, [span('🛒'), span(`Cart (${cart().length})`)]))
]), ]),
Div({ class: 'mt-4 grid grid-cols-2 gap-4' }, [ div({ class: 'mt-4 grid grid-cols-2 gap-4' }, [
Button({ button({
class: 'btn btn-outline h-32 flex flex-col', class: 'btn btn-outline h-32 flex flex-col',
onclick: () => { onclick: () => {
cart([...cart(), { id: Date.now(), name: 'New Product', price: 39, quantity: 1 }]); cart([...cart(), { id: Date.now(), name: 'New Product', price: 39, quantity: 1 }]);
Toast('Added to cart!', 'alert-success', 1500); Toast('Added to cart!', 'alert-success', 1500);
} }
}, Span({ class: 'flex flex-col items-center gap-1' }, [Span('📦'), Span('Add to Cart')])) }, span({ class: 'flex flex-col items-center gap-1' }, [span('📦'), span('Add to Cart')]))
]) ])
]) ])
}); });
@@ -353,22 +353,22 @@ const ResponsiveDrawer = () => {
const isOpen = $(false); const isOpen = $(false);
const activePage = $('home'); const activePage = $('home');
const MenuItems = () => Div({ class: 'flex flex-col gap-1 p-4' }, [ const MenuItems = () => div({ class: 'flex flex-col gap-1 p-4' }, [
Button({ button({
class: `btn btn-ghost justify-start ${activePage() === 'home' ? 'btn-active' : ''}`, class: `btn btn-ghost justify-start ${activePage() === 'home' ? 'btn-active' : ''}`,
onclick: () => { onclick: () => {
activePage('home'); activePage('home');
if (window.innerWidth < 1024) isOpen(false); if (window.innerWidth < 1024) isOpen(false);
} }
}, '🏠 Home'), }, '🏠 Home'),
Button({ button({
class: `btn btn-ghost justify-start ${activePage() === 'analytics' ? 'btn-active' : ''}`, class: `btn btn-ghost justify-start ${activePage() === 'analytics' ? 'btn-active' : ''}`,
onclick: () => { onclick: () => {
activePage('analytics'); activePage('analytics');
if (window.innerWidth < 1024) isOpen(false); if (window.innerWidth < 1024) isOpen(false);
} }
}, '📊 Analytics'), }, '📊 Analytics'),
Button({ button({
class: `btn btn-ghost justify-start ${activePage() === 'settings' ? 'btn-active' : ''}`, class: `btn btn-ghost justify-start ${activePage() === 'settings' ? 'btn-active' : ''}`,
onclick: () => { onclick: () => {
activePage('settings'); activePage('settings');
@@ -380,24 +380,24 @@ const ResponsiveDrawer = () => {
return Drawer({ return Drawer({
id: 'responsive-drawer', id: 'responsive-drawer',
open: isOpen, open: isOpen,
side: Div({ class: 'w-64' }, [ side: div({ class: 'w-64' }, [
Div({ class: 'text-xl font-bold p-4 border-b border-base-300' }, 'Menu'), div({ class: 'text-xl font-bold p-4 border-b border-base-300' }, 'Menu'),
MenuItems() MenuItems()
]), ]),
content: Div({ class: 'flex' }, [ content: div({ class: 'flex' }, [
Div({ class: 'hidden lg:block w-64 border-r border-base-300' }, [MenuItems()]), div({ class: 'hidden lg:block w-64 border-r border-base-300' }, [MenuItems()]),
Div({ class: 'flex-1 p-4' }, [ div({ class: 'flex-1 p-4' }, [
Div({ class: 'flex justify-between items-center lg:hidden mb-4' }, [ div({ class: 'flex justify-between items-center lg:hidden mb-4' }, [
Button({ button({
class: 'btn btn-ghost btn-circle', class: 'btn btn-ghost btn-circle',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, '☰'), }, '☰'),
Span({ class: 'text-lg font-bold' }, 'MyApp') span({ class: 'text-lg font-bold' }, 'MyApp')
]), ]),
Div({ class: 'card bg-base-200' }, [ div({ class: 'card bg-base-200' }, [
Div({ class: 'card-body' }, [ div({ class: 'card-body' }, [
Div({ class: 'text-2xl font-bold' }, () => activePage().charAt(0).toUpperCase() + activePage().slice(1)), div({ class: 'text-2xl font-bold' }, () => activePage().charAt(0).toUpperCase() + activePage().slice(1)),
Div({}, 'Content area. On desktop, the menu is always visible on the left.') div({}, 'Content area. On desktop, the menu is always visible on the left.')
]) ])
]) ])
]) ])
@@ -438,30 +438,30 @@ const FormDrawer = () => {
return Drawer({ return Drawer({
id: 'form-drawer', id: 'form-drawer',
open: isOpen, open: isOpen,
side: Div({ class: 'p-4 w-96' }, [ side: div({ class: 'p-4 w-96' }, [
Div({ class: 'flex justify-between items-center mb-4' }, [ div({ class: 'flex justify-between items-center mb-4' }, [
Span({ class: 'text-xl font-bold' }, 'Contact Us'), span({ class: 'text-xl font-bold' }, 'Contact Us'),
Button({ button({
class: 'btn btn-ghost btn-circle btn-sm', class: 'btn btn-ghost btn-circle btn-sm',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, '✕') }, '✕')
]), ]),
Div({ class: 'flex flex-col gap-4' }, [ div({ class: 'flex flex-col gap-4' }, [
Input({ input({
label: 'Name', label: 'Name',
value: name, value: name,
placeholder: 'Your name', placeholder: 'Your name',
oninput: (e) => name(e.target.value) oninput: (e) => name(e.target.value)
}), }),
Input({ input({
label: 'Email', label: 'Email',
type: 'email', type: 'email',
value: email, value: email,
placeholder: 'your@email.com', placeholder: 'your@email.com',
oninput: (e) => email(e.target.value) oninput: (e) => email(e.target.value)
}), }),
Div({ class: 'form-control' }, [ div({ class: 'form-control' }, [
Span({ class: 'label-text mb-1' }, 'Message'), span({ class: 'label-text mb-1' }, 'Message'),
h('textarea', { h('textarea', {
class: 'textarea textarea-bordered h-24', class: 'textarea textarea-bordered h-24',
placeholder: 'Your message', placeholder: 'Your message',
@@ -469,20 +469,20 @@ const FormDrawer = () => {
oninput: (e) => message(e.target.value) oninput: (e) => message(e.target.value)
}) })
]), ]),
Div({ class: 'flex gap-2 mt-2' }, [ div({ class: 'flex gap-2 mt-2' }, [
Button({ button({
class: 'btn btn-primary flex-1', class: 'btn btn-primary flex-1',
onclick: handleSubmit onclick: handleSubmit
}, 'Send'), }, 'Send'),
Button({ button({
class: 'btn btn-ghost flex-1', class: 'btn btn-ghost flex-1',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, 'Cancel') }, 'Cancel')
]) ])
]) ])
]), ]),
content: Div({ class: 'p-4 text-center' }, [ content: div({ class: 'p-4 text-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, 'Contact Us') }, 'Contact Us')

View File

@@ -139,9 +139,9 @@ mount(ActionsDemo, '#demo-actions');
```javascript ```javascript
const UserDropdown = () => { const UserDropdown = () => {
return Dropdown({ return Dropdown({
label: Span({ class: 'flex items-center gap-2' }, [ label: span({ class: 'flex items-center gap-2' }, [
Div({ class: 'avatar placeholder' }, [ div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-primary text-primary-content rounded-full w-8 h-8 flex items-center justify-center text-sm' }, 'JD') div({ class: 'bg-primary text-primary-content rounded-full w-8 h-8 flex items-center justify-center text-sm' }, 'JD')
]), ]),
'John Doe' 'John Doe'
]), ]),
@@ -209,15 +209,15 @@ const NotificationsDropdown = () => {
}; };
return Dropdown({ return Dropdown({
label: Span({ class: 'relative' }, [ label: span({ class: 'relative' }, [
'🔔', '🔔',
() => unreadCount() > 0 ? Span({ class: 'badge badge-xs badge-error absolute -top-1 -right-2' }, unreadCount()) : null () => unreadCount() > 0 ? span({ class: 'badge badge-xs badge-error absolute -top-1 -right-2' }, unreadCount()) : null
]), ]),
class: 'dropdown-end', class: 'dropdown-end',
items: () => notifications().map(notif => ({ items: () => notifications().map(notif => ({
label: Div({ class: 'flex flex-col' }, [ label: div({ class: 'flex flex-col' }, [
Span({ class: 'font-medium' }, notif.title), span({ class: 'font-medium' }, notif.title),
Span({ class: 'text-xs opacity-60' }, notif.time) span({ class: 'text-xs opacity-60' }, notif.time)
]), ]),
class: notif.read ? '' : 'bg-primary/5', class: notif.read ? '' : 'bg-primary/5',
onclick: () => markAsRead(notif.id) onclick: () => markAsRead(notif.id)
@@ -245,7 +245,7 @@ const VariantsDemo = () => {
{ label: 'Item 3', onclick: () => Toast('Item 3', 'alert-info', 2000) } { label: 'Item 3', onclick: () => Toast('Item 3', 'alert-info', 2000) }
]; ];
return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [ return div({ class: 'flex flex-wrap gap-4 justify-center' }, [
Dropdown({ label: 'Default', items: commonItems }), Dropdown({ label: 'Default', items: commonItems }),
Dropdown({ label: 'With Icon', icon: '☰', items: commonItems }), Dropdown({ label: 'With Icon', icon: '☰', items: commonItems }),
Dropdown({ label: 'End Position', class: 'dropdown-end', items: commonItems }) Dropdown({ label: 'End Position', class: 'dropdown-end', items: commonItems })

View File

@@ -64,7 +64,7 @@ Fab({
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ return div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [
Fab({ Fab({
icon: '', icon: '',
actions: [ actions: [
@@ -89,7 +89,7 @@ mount(BasicDemo, '#demo-basic');
```javascript ```javascript
const LabelDemo = () => { const LabelDemo = () => {
return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ return div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [
Fab({ Fab({
label: 'Create', label: 'Create',
icon: '✨', icon: '✨',
@@ -117,9 +117,9 @@ mount(LabelDemo, '#demo-label');
const PositionsDemo = () => { const PositionsDemo = () => {
const position = $('bottom-6 right-6'); const position = $('bottom-6 right-6');
return Div({ class: 'relative h-[500px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ return div({ class: 'relative h-[500px] w-full bg-base-100 rounded-lg overflow-hidden' }, [
Div({ class: 'absolute top-4 left-4 z-20 bg-base-200 p-2 rounded-lg shadow' }, [ div({ class: 'absolute top-4 left-4 z-20 bg-base-200 p-2 rounded-lg shadow' }, [
Select({ select({
items: [ items: [
{ value: 'bottom-6 right-6', label: 'Bottom Right' }, { value: 'bottom-6 right-6', label: 'Bottom Right' },
{ value: 'bottom-6 left-6', label: 'Bottom Left' }, { value: 'bottom-6 left-6', label: 'Bottom Left' },
@@ -130,7 +130,7 @@ const PositionsDemo = () => {
onchange: (e) => position(e.target.value) onchange: (e) => position(e.target.value)
}) })
]), ]),
Div({ class: 'absolute inset-0 flex items-center justify-center text-sm opacity-50 pointer-events-none' }, [ div({ class: 'absolute inset-0 flex items-center justify-center text-sm opacity-50 pointer-events-none' }, [
'FAB position changes relative to this container' 'FAB position changes relative to this container'
]), ]),
Fab({ Fab({
@@ -171,9 +171,9 @@ const ColorsDemo = () => {
error: { class: 'btn-error', icon: '🔴' } error: { class: 'btn-error', icon: '🔴' }
}; };
return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ return div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [
Div({ class: 'absolute top-4 left-4 z-20 bg-base-200 p-2 rounded-lg shadow' }, [ div({ class: 'absolute top-4 left-4 z-20 bg-base-200 p-2 rounded-lg shadow' }, [
Select({ select({
items: Object.keys(variants).map(v => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) })), items: Object.keys(variants).map(v => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) })),
value: variant, value: variant,
onchange: (e) => variant(e.target.value) onchange: (e) => variant(e.target.value)
@@ -229,7 +229,7 @@ const ReactiveActions = () => {
} }
]; ];
return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ return div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [
Fab({ Fab({
icon: () => count() > 0 ? `🔢 ${count()}` : '🎛️', icon: () => count() > 0 ? `🔢 ${count()}` : '🎛️',
actions: actions actions: actions
@@ -258,11 +258,11 @@ const DocumentActions = () => {
setTimeout(() => saved(false), 3000); setTimeout(() => saved(false), 3000);
}; };
return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ return div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [
Div({ class: 'absolute inset-0 flex flex-col items-center justify-center' }, [ div({ class: 'absolute inset-0 flex flex-col items-center justify-center' }, [
Div({ class: 'text-6xl mb-4' }, '📄'), div({ class: 'text-6xl mb-4' }, '📄'),
Div({ class: 'text-sm opacity-70' }, 'Untitled Document'), div({ class: 'text-sm opacity-70' }, 'Untitled Document'),
() => saved() ? Div({ class: 'mt-4' }, Alert({ type: 'success', message: '✓ Saved successfully' })) : null () => saved() ? div({ class: 'mt-4' }, Alert({ type: 'success', message: '✓ Saved successfully' })) : null
]), ]),
Fab({ Fab({
icon: '✏️', icon: '✏️',
@@ -291,11 +291,11 @@ mount(DocumentActions, '#demo-document');
const MessagingFAB = () => { const MessagingFAB = () => {
const unread = $(3); const unread = $(3);
return Div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ return div({ class: 'relative h-[300px] w-full bg-base-100 rounded-lg overflow-hidden' }, [
Div({ class: 'absolute inset-0 flex flex-col items-center justify-center' }, [ div({ class: 'absolute inset-0 flex flex-col items-center justify-center' }, [
Div({ class: 'text-6xl mb-4' }, '💬'), div({ class: 'text-6xl mb-4' }, '💬'),
Div({ class: 'text-sm opacity-70' }, 'Messages'), div({ class: 'text-sm opacity-70' }, 'Messages'),
() => unread() > 0 ? Div({ class: 'badge badge-error mt-2' }, `${unread()} unread`) : null () => unread() > 0 ? div({ class: 'badge badge-error mt-2' }, `${unread()} unread`) : null
]), ]),
Fab({ Fab({
icon: () => `💬${unread() > 0 ? ` ${unread()}` : ''}`, icon: () => `💬${unread() > 0 ? ` ${unread()}` : ''}`,
@@ -353,22 +353,22 @@ const VariantsDemo = () => {
{ icon: '📅', label: 'Schedule', onclick: () => Toast('Scheduled', 'alert-info', 2000) } { icon: '📅', label: 'Schedule', onclick: () => Toast('Scheduled', 'alert-info', 2000) }
]; ];
return Div({ class: 'relative h-[400px] w-full bg-base-100 rounded-lg overflow-hidden' }, [ return div({ class: 'relative h-[400px] w-full bg-base-100 rounded-lg overflow-hidden' }, [
Div({ class: 'grid grid-cols-2 gap-4 p-4 h-full' }, [ div({ class: 'grid grid-cols-2 gap-4 p-4 h-full' }, [
Div({ class: 'relative border rounded-lg bg-base-200' }, [ div({ class: 'relative border rounded-lg bg-base-200' }, [
Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Primary'), span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Primary'),
Fab({ icon: '🔵', class: 'btn-primary', actions, position: 'bottom-6 left-6' }) Fab({ icon: '🔵', class: 'btn-primary', actions, position: 'bottom-6 left-6' })
]), ]),
Div({ class: 'relative border rounded-lg bg-base-200' }, [ div({ class: 'relative border rounded-lg bg-base-200' }, [
Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Secondary'), span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Secondary'),
Fab({ icon: '🟣', class: 'btn-secondary', actions, position: 'bottom-6 right-6' }) Fab({ icon: '🟣', class: 'btn-secondary', actions, position: 'bottom-6 right-6' })
]), ]),
Div({ class: 'relative border rounded-lg bg-base-200' }, [ div({ class: 'relative border rounded-lg bg-base-200' }, [
Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Accent'), span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Accent'),
Fab({ icon: '🔴', class: 'btn-accent', actions, position: 'top-6 left-6' }) Fab({ icon: '🔴', class: 'btn-accent', actions, position: 'top-6 left-6' })
]), ]),
Div({ class: 'relative border rounded-lg bg-base-200' }, [ div({ class: 'relative border rounded-lg bg-base-200' }, [
Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Success'), span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Success'),
Fab({ icon: '🟢', class: 'btn-success', actions, position: 'top-6 right-6' }) Fab({ icon: '🟢', class: 'btn-success', actions, position: 'top-6 right-6' })
]) ])
]) ])

View File

@@ -33,8 +33,8 @@ Fieldset({
legend: "Personal Information", legend: "Personal Information",
class: "fieldset-primary w-full max-w-md" class: "fieldset-primary w-full max-w-md"
}, [ }, [
Input({ label: "Name", placeholder: "Enter your name" }), input({ label: "Name", placeholder: "Enter your name" }),
Input({ label: "Email", type: "email" }) input({ label: "Email", type: "email" })
]); ]);
``` ```
@@ -51,14 +51,14 @@ Fieldset({
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Fieldset({ return fieldset({
legend: 'User Information', legend: 'User Information',
class: 'w-full max-w-md mx-auto' class: 'w-full max-w-md mx-auto'
}, [ }, [
Div({ class: 'space-y-4' }, [ div({ class: 'space-y-4' }, [
Input({ label: 'Full Name', placeholder: 'Enter your name' }), input({ label: 'Full Name', placeholder: 'Enter your name' }),
Input({ label: 'Email', type: 'email', placeholder: 'user@example.com' }), input({ label: 'Email', type: 'email', placeholder: 'user@example.com' }),
Input({ label: 'Phone', type: 'tel', placeholder: '+1 234 567 890' }) input({ label: 'Phone', type: 'tel', placeholder: '+1 234 567 890' })
]) ])
]); ]);
}; };
@@ -80,18 +80,18 @@ const ReactiveDemo = () => {
const email = $(''); const email = $('');
const isValid = () => name().length > 0 && email().includes('@'); const isValid = () => name().length > 0 && email().includes('@');
return Fieldset({ return fieldset({
legend: () => isValid() ? '✓ Valid Form' : '✗ Incomplete Form', legend: () => isValid() ? '✓ Valid Form' : '✗ Incomplete Form',
class: 'w-full max-w-md mx-auto' class: 'w-full max-w-md mx-auto'
}, [ }, [
Div({ class: 'space-y-4' }, [ div({ class: 'space-y-4' }, [
Input({ input({
label: 'Full Name', label: 'Full Name',
value: name, value: name,
oninput: (e) => name(e.target.value), oninput: (e) => name(e.target.value),
placeholder: 'Enter your name' placeholder: 'Enter your name'
}), }),
Input({ input({
label: 'Email', label: 'Email',
type: 'email', type: 'email',
value: email, value: email,
@@ -123,17 +123,17 @@ const AddressDemo = () => {
const zip = $(''); const zip = $('');
const country = $('us'); const country = $('us');
return Fieldset({ return fieldset({
legend: Span({ class: 'flex items-center gap-2' }, ['📍', 'Shipping Address']), legend: span({ class: 'flex items-center gap-2' }, ['📍', 'Shipping Address']),
class: 'w-full max-w-md mx-auto' class: 'w-full max-w-md mx-auto'
}, [ }, [
Div({ class: 'space-y-4' }, [ div({ class: 'space-y-4' }, [
Input({ label: 'Street Address', value: address, placeholder: '123 Main St', oninput: (e) => address(e.target.value) }), input({ label: 'Street Address', value: address, placeholder: '123 Main St', oninput: (e) => address(e.target.value) }),
Div({ class: 'grid grid-cols-2 gap-4' }, [ div({ class: 'grid grid-cols-2 gap-4' }, [
Input({ label: 'City', value: city, placeholder: 'City', oninput: (e) => city(e.target.value) }), input({ label: 'City', value: city, placeholder: 'City', oninput: (e) => city(e.target.value) }),
Input({ label: 'ZIP Code', value: zip, placeholder: 'ZIP', oninput: (e) => zip(e.target.value) }) input({ label: 'ZIP Code', value: zip, placeholder: 'ZIP', oninput: (e) => zip(e.target.value) })
]), ]),
Select({ select({
label: 'Country', label: 'Country',
value: country, value: country,
items: [ items: [
@@ -165,21 +165,21 @@ const PaymentDemo = () => {
const expiry = $(''); const expiry = $('');
const cvv = $(''); const cvv = $('');
return Fieldset({ return fieldset({
legend: Span({ class: 'flex items-center gap-2' }, ['💳', 'Payment Details']), legend: span({ class: 'flex items-center gap-2' }, ['💳', 'Payment Details']),
class: 'w-full max-w-md mx-auto' class: 'w-full max-w-md mx-auto'
}, [ }, [
Div({ class: 'space-y-4' }, [ div({ class: 'space-y-4' }, [
Div({ class: 'flex gap-4' }, [ div({ class: 'flex gap-4' }, [
Radio({ label: 'Credit Card', value: method, inputValue: 'credit', onclick: () => method('credit') }), Radio({ label: 'Credit Card', value: method, inputValue: 'credit', onclick: () => method('credit') }),
Radio({ label: 'PayPal', value: method, inputValue: 'paypal', onclick: () => method('paypal') }), Radio({ label: 'PayPal', value: method, inputValue: 'paypal', onclick: () => method('paypal') }),
Radio({ label: 'Bank Transfer', value: method, inputValue: 'bank', onclick: () => method('bank') }) Radio({ label: 'Bank Transfer', value: method, inputValue: 'bank', onclick: () => method('bank') })
]), ]),
() => method() === 'credit' ? Div({ class: 'space-y-4' }, [ () => method() === 'credit' ? div({ class: 'space-y-4' }, [
Input({ label: 'Card Number', value: cardNumber, placeholder: '1234 5678 9012 3456', oninput: (e) => cardNumber(e.target.value) }), input({ label: 'Card Number', value: cardNumber, placeholder: '1234 5678 9012 3456', oninput: (e) => cardNumber(e.target.value) }),
Div({ class: 'grid grid-cols-2 gap-4' }, [ div({ class: 'grid grid-cols-2 gap-4' }, [
Input({ label: 'Expiry Date', value: expiry, placeholder: 'MM/YY', oninput: (e) => expiry(e.target.value) }), input({ label: 'Expiry Date', value: expiry, placeholder: 'MM/YY', oninput: (e) => expiry(e.target.value) }),
Input({ label: 'CVV', type: 'password', value: cvv, placeholder: '123', oninput: (e) => cvv(e.target.value) }) input({ label: 'CVV', type: 'password', value: cvv, placeholder: '123', oninput: (e) => cvv(e.target.value) })
]) ])
]) : null, ]) : null,
() => method() === 'paypal' ? Alert({ type: 'info', message: 'You will be redirected to PayPal after confirming.' }) : null, () => method() === 'paypal' ? Alert({ type: 'info', message: 'You will be redirected to PayPal after confirming.' }) : null,
@@ -205,20 +205,20 @@ const PreferencesDemo = () => {
const language = $('en'); const language = $('en');
const notifications = $(true); const notifications = $(true);
return Fieldset({ return fieldset({
legend: Span({ class: 'flex items-center gap-2' }, ['⚙️', 'Preferences']), legend: span({ class: 'flex items-center gap-2' }, ['⚙️', 'Preferences']),
class: 'w-full max-w-md mx-auto' class: 'w-full max-w-md mx-auto'
}, [ }, [
Div({ class: 'space-y-4' }, [ div({ class: 'space-y-4' }, [
Div({ class: 'form-control' }, [ div({ class: 'form-control' }, [
Span({ class: 'label-text mb-2' }, 'Theme'), span({ class: 'label-text mb-2' }, 'Theme'),
Div({ class: 'flex gap-4' }, [ div({ class: 'flex gap-4' }, [
Radio({ label: 'Light', value: theme, inputValue: 'light', onclick: () => theme('light') }), Radio({ label: 'Light', value: theme, inputValue: 'light', onclick: () => theme('light') }),
Radio({ label: 'Dark', value: theme, inputValue: 'dark', onclick: () => theme('dark') }), Radio({ label: 'Dark', value: theme, inputValue: 'dark', onclick: () => theme('dark') }),
Radio({ label: 'System', value: theme, inputValue: 'system', onclick: () => theme('system') }) Radio({ label: 'System', value: theme, inputValue: 'system', onclick: () => theme('system') })
]) ])
]), ]),
Select({ select({
label: 'Language', label: 'Language',
value: language, value: language,
items: [ items: [
@@ -265,15 +265,15 @@ const RegistrationDemo = () => {
} }
}; };
return Fieldset({ return fieldset({
legend: Span({ class: 'flex items-center gap-2' }, ['📝', 'Create Account']), legend: span({ class: 'flex items-center gap-2' }, ['📝', 'Create Account']),
class: 'w-full max-w-md mx-auto' class: 'w-full max-w-md mx-auto'
}, [ }, [
Div({ class: 'space-y-4' }, [ div({ class: 'space-y-4' }, [
Input({ label: 'Username', value: username, placeholder: 'Choose a username', oninput: (e) => username(e.target.value) }), input({ label: 'Username', value: username, placeholder: 'Choose a username', oninput: (e) => username(e.target.value) }),
Input({ label: 'Email', type: 'email', value: email, placeholder: 'your@email.com', oninput: (e) => email(e.target.value) }), input({ label: 'Email', type: 'email', value: email, placeholder: 'your@email.com', oninput: (e) => email(e.target.value) }),
Input({ label: 'Password', type: 'password', value: password, placeholder: 'Min. 6 characters', oninput: (e) => password(e.target.value) }), input({ label: 'Password', type: 'password', value: password, placeholder: 'Min. 6 characters', oninput: (e) => password(e.target.value) }),
Input({ input({
label: 'Confirm Password', label: 'Confirm Password',
type: 'password', type: 'password',
value: confirmPassword, value: confirmPassword,
@@ -286,7 +286,7 @@ const RegistrationDemo = () => {
onclick: () => accepted(!accepted()) onclick: () => accepted(!accepted())
}), }),
() => !isFormValid() && (username() || email() || password()) ? Alert({ type: 'warning', message: 'Please complete all fields correctly' }) : null, () => !isFormValid() && (username() || email() || password()) ? Alert({ type: 'warning', message: 'Please complete all fields correctly' }) : null,
Button({ button({
class: 'btn btn-primary w-full', class: 'btn btn-primary w-full',
onclick: handleSubmit, onclick: handleSubmit,
disabled: () => !isFormValid() disabled: () => !isFormValid()
@@ -308,16 +308,16 @@ mount(RegistrationDemo, '#demo-registration');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
const commonContent = Div({ class: 'space-y-4' }, [ const commonContent = div({ class: 'space-y-4' }, [
Input({ label: 'Field 1', placeholder: 'Enter value' }), input({ label: 'Field 1', placeholder: 'Enter value' }),
Input({ label: 'Field 2', placeholder: 'Enter value' }), input({ label: 'Field 2', placeholder: 'Enter value' }),
Button({ class: 'btn btn-primary' }, 'Submit') button({ class: 'btn btn-primary' }, 'Submit')
]); ]);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Fieldset({ legend: 'Default Fieldset', class: 'w-full' }, [commonContent]), fieldset({ legend: 'Default Fieldset', class: 'w-full' }, [commonContent]),
Fieldset({ legend: 'With Shadow', class: 'w-full shadow-lg' }, [commonContent]), fieldset({ legend: 'With Shadow', class: 'w-full shadow-lg' }, [commonContent]),
Fieldset({ legend: 'With Background', class: 'w-full bg-base-100' }, [commonContent]) fieldset({ legend: 'With Background', class: 'w-full bg-base-100' }, [commonContent])
]); ]);
}; };
mount(VariantsDemo, '#demo-variants'); mount(VariantsDemo, '#demo-variants');

View File

@@ -30,7 +30,7 @@ Indicator uses **daisyUI Indicator and Badge classes**:
```javascript ```javascript
Indicator({ value: "3", class: "badge-primary" }, Indicator({ value: "3", class: "badge-primary" },
Button({ class: "btn" }, "Notifications") button({ class: "btn" }, "Notifications")
); );
``` ```
@@ -47,15 +47,15 @@ Indicator({ value: "3", class: "badge-primary" },
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Div({ class: 'flex flex-wrap gap-8 justify-center' }, [ return div({ class: 'flex flex-wrap gap-8 justify-center' }, [
Indicator({ value: '3', class: 'badge-primary' }, Indicator({ value: '3', class: 'badge-primary' },
Div({ class: 'w-16 h-16 bg-base-300 rounded-lg flex items-center justify-center' }, '📦') div({ class: 'w-16 h-16 bg-base-300 rounded-lg flex items-center justify-center' }, '📦')
), ),
Indicator({ value: '99+', class: 'badge-secondary' }, Indicator({ value: '99+', class: 'badge-secondary' },
Div({ class: 'w-16 h-16 bg-base-300 rounded-lg flex items-center justify-center' }, '🔔') div({ class: 'w-16 h-16 bg-base-300 rounded-lg flex items-center justify-center' }, '🔔')
), ),
Indicator({ value: 'New', class: 'badge-accent' }, Indicator({ value: 'New', class: 'badge-accent' },
Div({ class: 'w-16 h-16 bg-base-300 rounded-lg flex items-center justify-center' }, '✨') div({ class: 'w-16 h-16 bg-base-300 rounded-lg flex items-center justify-center' }, '✨')
) )
]); ]);
}; };
@@ -73,20 +73,20 @@ mount(BasicDemo, '#demo-basic');
```javascript ```javascript
const StatusDemo = () => { const StatusDemo = () => {
return Div({ class: 'flex flex-wrap gap-8 justify-center' }, [ return div({ class: 'flex flex-wrap gap-8 justify-center' }, [
Indicator({ value: '●', class: 'badge-success badge-xs' }, Indicator({ value: '●', class: 'badge-success badge-xs' },
Div({ class: 'avatar placeholder' }, [ div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-neutral text-neutral-content rounded-full w-12 h-12 flex items-center justify-center' }, 'JD') div({ class: 'bg-neutral text-neutral-content rounded-full w-12 h-12 flex items-center justify-center' }, 'JD')
]) ])
), ),
Indicator({ value: '●', class: 'badge-warning badge-xs' }, Indicator({ value: '●', class: 'badge-warning badge-xs' },
Div({ class: 'avatar placeholder' }, [ div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-neutral text-neutral-content rounded-full w-12 h-12 flex items-center justify-center' }, 'JS') div({ class: 'bg-neutral text-neutral-content rounded-full w-12 h-12 flex items-center justify-center' }, 'JS')
]) ])
), ),
Indicator({ value: '●', class: 'badge-error badge-xs' }, Indicator({ value: '●', class: 'badge-error badge-xs' },
Div({ class: 'avatar placeholder' }, [ div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-neutral text-neutral-content rounded-full w-12 h-12 flex items-center justify-center' }, 'BC') div({ class: 'bg-neutral text-neutral-content rounded-full w-12 h-12 flex items-center justify-center' }, 'BC')
]) ])
) )
]); ]);
@@ -107,22 +107,22 @@ mount(StatusDemo, '#demo-status');
const ReactiveDemo = () => { const ReactiveDemo = () => {
const count = $(0); const count = $(0);
return Div({ class: 'flex flex-col gap-4 items-center' }, [ return div({ class: 'flex flex-col gap-4 items-center' }, [
Indicator({ Indicator({
value: () => count() > 0 ? count() : null, value: () => count() > 0 ? count() : null,
class: 'badge-primary' class: 'badge-primary'
}, },
Button({ button({
class: 'btn btn-lg btn-primary', class: 'btn btn-lg btn-primary',
onclick: () => count(count() + 1) onclick: () => count(count() + 1)
}, 'Notifications') }, 'Notifications')
), ),
Div({ class: 'flex gap-2' }, [ div({ class: 'flex gap-2' }, [
Button({ button({
class: 'btn btn-sm', class: 'btn btn-sm',
onclick: () => count(Math.max(0, count() - 1)) onclick: () => count(Math.max(0, count() - 1))
}, 'Decrease'), }, 'Decrease'),
Button({ button({
class: 'btn btn-sm btn-ghost', class: 'btn btn-sm btn-ghost',
onclick: () => count(0) onclick: () => count(0)
}, 'Clear') }, 'Clear')
@@ -161,24 +161,24 @@ const CartDemo = () => {
const total = () => cart().reduce((sum, item) => sum + item.price, 0); const total = () => cart().reduce((sum, item) => sum + item.price, 0);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Indicator({ Indicator({
value: () => cart().length, value: () => cart().length,
class: 'badge-primary' class: 'badge-primary'
}, },
Button({ class: 'btn', onclick: addItem }, '🛒 Add to Cart') button({ class: 'btn', onclick: addItem }, '🛒 Add to Cart')
), ),
Span({ class: 'text-lg font-bold' }, () => `Total: $${total()}`) span({ class: 'text-lg font-bold' }, () => `Total: $${total()}`)
]), ]),
() => cart().length === 0 () => cart().length === 0
? Div({ class: 'alert alert-soft text-center' }, 'Cart is empty') ? div({ class: 'alert alert-soft text-center' }, 'Cart is empty')
: Div({ class: 'flex flex-col gap-2' }, cart().map(item => : div({ class: 'flex flex-col gap-2' }, cart().map(item =>
Div({ class: 'flex justify-between items-center p-2 bg-base-200 rounded-lg' }, [ div({ class: 'flex justify-between items-center p-2 bg-base-200 rounded-lg' }, [
Span({}, item.name), span({}, item.name),
Div({ class: 'flex gap-2 items-center' }, [ div({ class: 'flex gap-2 items-center' }, [
Span({ class: 'text-sm font-bold' }, `$${item.price}`), span({ class: 'text-sm font-bold' }, `$${item.price}`),
Button({ button({
class: 'btn btn-xs btn-ghost btn-circle', class: 'btn btn-xs btn-ghost btn-circle',
onclick: () => removeItem(item.id) onclick: () => removeItem(item.id)
}, '✕') }, '✕')
@@ -219,15 +219,15 @@ const InboxDemo = () => {
} }
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Indicator({ Indicator({
value: () => unread(), value: () => unread(),
class: 'badge-primary' class: 'badge-primary'
}, },
Span({ class: 'text-lg font-bold' }, 'Inbox') span({ class: 'text-lg font-bold' }, 'Inbox')
), ),
Button({ button({
class: 'btn btn-sm btn-ghost', class: 'btn btn-sm btn-ghost',
onclick: () => { onclick: () => {
messages().forEach(m => m.read = true); messages().forEach(m => m.read = true);
@@ -236,14 +236,14 @@ const InboxDemo = () => {
} }
}, 'Mark all read') }, 'Mark all read')
]), ]),
Div({ class: 'flex flex-col gap-2' }, () => messages().map(msg => div({ class: 'flex flex-col gap-2' }, () => messages().map(msg =>
Div({ div({
class: `p-3 rounded-lg cursor-pointer transition-all ${msg.read ? 'bg-base-200 opacity-60' : 'bg-primary/10 border-l-4 border-primary'}`, class: `p-3 rounded-lg cursor-pointer transition-all ${msg.read ? 'bg-base-200 opacity-60' : 'bg-primary/10 border-l-4 border-primary'}`,
onclick: () => markAsRead(msg.id) onclick: () => markAsRead(msg.id)
}, [ }, [
Div({ class: 'font-medium' }, msg.from), div({ class: 'font-medium' }, msg.from),
Div({ class: 'text-sm' }, msg.subject), div({ class: 'text-sm' }, msg.subject),
!msg.read && Span({ class: 'badge badge-xs badge-primary mt-1' }, 'New') !msg.read && span({ class: 'badge badge-xs badge-primary mt-1' }, 'New')
]) ])
)) ))
]); ]);
@@ -263,20 +263,20 @@ mount(InboxDemo, '#demo-inbox');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'flex flex-wrap gap-8 justify-center' }, [ return div({ class: 'flex flex-wrap gap-8 justify-center' }, [
Indicator({ value: '3', class: 'badge-primary badge-sm' }, Indicator({ value: '3', class: 'badge-primary badge-sm' },
Div({ class: 'w-12 h-12 bg-base-300 rounded-lg flex items-center justify-center' }, '📧') div({ class: 'w-12 h-12 bg-base-300 rounded-lg flex items-center justify-center' }, '📧')
), ),
Indicator({ value: '99+', class: 'badge-secondary badge-md' }, Indicator({ value: '99+', class: 'badge-secondary badge-md' },
Div({ class: 'w-12 h-12 bg-base-300 rounded-lg flex items-center justify-center' }, '🔔') div({ class: 'w-12 h-12 bg-base-300 rounded-lg flex items-center justify-center' }, '🔔')
), ),
Indicator({ value: '●', class: 'badge-success badge-xs' }, Indicator({ value: '●', class: 'badge-success badge-xs' },
Div({ class: 'avatar' }, [ div({ class: 'avatar' }, [
Div({ class: 'w-10 h-10 rounded-full bg-primary' }) div({ class: 'w-10 h-10 rounded-full bg-primary' })
]) ])
), ),
Indicator({ value: '!', class: 'badge-error badge-sm' }, Indicator({ value: '!', class: 'badge-error badge-sm' },
Div({ class: 'w-12 h-12 bg-base-300 rounded-lg flex items-center justify-center' }, '⚠️') div({ class: 'w-12 h-12 bg-base-300 rounded-lg flex items-center justify-center' }, '⚠️')
) )
]); ]);
}; };

View File

@@ -43,7 +43,7 @@ const { Input, mount } = window;
const BasicDemo = () => { const BasicDemo = () => {
const name = $(""); const name = $("");
return Input({ return input({
placeholder: "Enter your name", placeholder: "Enter your name",
value: name, value: name,
oninput: (e) => name(e.target.value) oninput: (e) => name(e.target.value)
@@ -68,7 +68,7 @@ const { InputLabel, Div, Icon, mount } = window;
const IconDemo = () => { const IconDemo = () => {
const email = $(""); const email = $("");
return Div({ class: "input input-bordered flex items-center gap-2" }, [ return div({ class: "input input-bordered flex items-center gap-2" }, [
Icon("✉️"), Icon("✉️"),
h("input", { h("input", {
class: "grow", class: "grow",
@@ -97,7 +97,7 @@ const { Input, Div, Icon, Swap, mount } = window;
const PasswordDemo = () => { const PasswordDemo = () => {
const password = $(""); const password = $("");
const visible = $(false); const visible = $(false);
return Div({ class: "input input-bordered flex items-center gap-2" }, [ return div({ class: "input input-bordered flex items-center gap-2" }, [
Icon("icon-[lucide--lock]"), Icon("icon-[lucide--lock]"),
h("input", { h("input", {
type: () => (visible() ? "text" : "password"), type: () => (visible() ? "text" : "password"),
@@ -133,9 +133,9 @@ const { Input, Div, Span, mount } = window;
const LabelDemo = () => { const LabelDemo = () => {
const email = $(""); const email = $("");
return Div({ class: "floating-label" }, [ return div({ class: "floating-label" }, [
Span("Email"), span("Email"),
Input({ input({
type: "email", type: "email",
value: email, value: email,
placeholder: " ", placeholder: " ",
@@ -163,7 +163,7 @@ const { Input, Tooltip, mount } = window;
const TooltipDemo = () => { const TooltipDemo = () => {
const username = $(""); const username = $("");
return Tooltip({ tip: "Must be at least 3 characters" }, [ return Tooltip({ tip: "Must be at least 3 characters" }, [
Input({ input({
placeholder: "Username", placeholder: "Username",
value: username, value: username,
oninput: (e) => username(e.target.value) oninput: (e) => username(e.target.value)
@@ -190,7 +190,7 @@ const { Input, Div, mount } = window;
const ErrorDemo = () => { const ErrorDemo = () => {
const email = $(""); const email = $("");
const isValid = () => email().includes("@"); const isValid = () => email().includes("@");
return Div({ class: "flex flex-col gap-2" }, [ return div({ class: "flex flex-col gap-2" }, [
h("input", { h("input", {
type: "email", type: "email",
class: () => `input input-bordered ${email() && !isValid() ? "input-error" : ""}`, class: () => `input input-bordered ${email() && !isValid() ? "input-error" : ""}`,
@@ -198,7 +198,7 @@ const ErrorDemo = () => {
placeholder: "mail@example.com", placeholder: "mail@example.com",
oninput: (e) => email(e.target.value) oninput: (e) => email(e.target.value)
}), }),
() => email() && !isValid() ? Div({ class: "text-error text-sm" }, "Enter a valid email") : null () => email() && !isValid() ? div({ class: "text-error text-sm" }, "Enter a valid email") : null
]); ]);
}; };
mount(ErrorDemo, "#demo-error"); mount(ErrorDemo, "#demo-error");
@@ -217,7 +217,7 @@ mount(ErrorDemo, "#demo-error");
const { Input, mount } = window; const { Input, mount } = window;
const DisabledDemo = () => { const DisabledDemo = () => {
return Input({ value: "john.doe", disabled: true }); return input({ value: "john.doe", disabled: true });
}; };
mount(DisabledDemo, "#demo-disabled"); mount(DisabledDemo, "#demo-disabled");
``` ```
@@ -236,18 +236,18 @@ const { Input, Div, mount } = window;
const VariantsDemo = () => { const VariantsDemo = () => {
const text = $(""); const text = $("");
return Div({ class: "flex flex-col gap-4" }, [ return div({ class: "flex flex-col gap-4" }, [
Input({ placeholder: "Default", value: text, oninput: (e) => text(e.target.value) }), input({ placeholder: "Default", value: text, oninput: (e) => text(e.target.value) }),
Input({ class: "input-primary", placeholder: "Primary", value: $("") }), input({ class: "input-primary", placeholder: "Primary", value: $("") }),
Input({ class: "input-secondary", placeholder: "Secondary", value: $("") }), input({ class: "input-secondary", placeholder: "Secondary", value: $("") }),
Input({ class: "input-accent", placeholder: "Accent", value: $("") }), input({ class: "input-accent", placeholder: "Accent", value: $("") }),
Input({ class: "input-ghost", placeholder: "Ghost", value: $("") }), input({ class: "input-ghost", placeholder: "Ghost", value: $("") }),
Input({ class: "input-info", placeholder: "Info", value: $("") }), input({ class: "input-info", placeholder: "Info", value: $("") }),
Input({ class: "input-success", placeholder: "Success", value: $("") }), input({ class: "input-success", placeholder: "Success", value: $("") }),
Input({ class: "input-warning", placeholder: "Warning", value: $("") }), input({ class: "input-warning", placeholder: "Warning", value: $("") }),
Input({ class: "input-error", placeholder: "Error", value: $("") }), input({ class: "input-error", placeholder: "Error", value: $("") }),
Input({ type: "number", placeholder: "Number", value: $(0), oninput: (e) => e.target.value }), input({ type: "number", placeholder: "Number", value: $(0), oninput: (e) => e.target.value }),
Input({ type: "date", value: $("2024-01-01") }) input({ type: "date", value: $("2024-01-01") })
]); ]);
}; };
mount(VariantsDemo, "#demo-variants"); mount(VariantsDemo, "#demo-variants");

View File

@@ -46,8 +46,8 @@ const BasicDemo = () => {
return List({ return List({
items: items, items: items,
render: (item) => render: (item) =>
Div({ class: "p-3 hover:bg-base-200 transition-colors" }, [ div({ class: "p-3 hover:bg-base-200 transition-colors" }, [
Span({ class: "font-medium" }, item), span({ class: "font-medium" }, item),
]), ]),
}); });
}; };
@@ -73,15 +73,15 @@ const HeaderDemo = () => {
return List({ return List({
items: users, items: users,
header: Div( header: div(
{ class: "p-3 bg-primary/10 font-bold border-b border-base-300" }, { class: "p-3 bg-primary/10 font-bold border-b border-base-300" },
"Active Users", "Active Users",
), ),
render: (user) => render: (user) =>
Div({ class: "p-3 border-b border-base-300 hover:bg-base-200" }, [ div({ class: "p-3 border-b border-base-300 hover:bg-base-200" }, [
Div({ class: "font-medium" }, user.name), div({ class: "font-medium" }, user.name),
Div({ class: "text-sm opacity-70" }, user.email), div({ class: "text-sm opacity-70" }, user.email),
Span( span(
{ {
class: `badge badge-sm ${user.status === "active" ? "badge-success" : "badge-ghost"} mt-1`, class: `badge badge-sm ${user.status === "active" ? "badge-success" : "badge-ghost"} mt-1`,
}, },
@@ -118,18 +118,18 @@ const IconsDemo = () => {
return List({ return List({
items: settings, items: settings,
render: (item) => render: (item) =>
Div( div(
{ {
class: class:
"flex gap-3 p-3 hover:bg-base-200 transition-colors cursor-pointer", "flex gap-3 p-3 hover:bg-base-200 transition-colors cursor-pointer",
}, },
[ [
Div({ class: "text-2xl" }, item.icon), div({ class: "text-2xl" }, item.icon),
Div({ class: "flex-1" }, [ div({ class: "flex-1" }, [
Div({ class: "font-medium" }, item.label), div({ class: "font-medium" }, item.label),
Div({ class: "text-sm opacity-60" }, item.description), div({ class: "text-sm opacity-60" }, item.description),
]), ]),
Span({ class: "opacity-40" }, "→"), span({ class: "opacity-40" }, "→"),
], ],
), ),
}); });
@@ -178,17 +178,17 @@ const BadgesDemo = () => {
return List({ return List({
items: notifications, items: notifications,
render: (item) => render: (item) =>
Div( div(
{ {
class: `flex justify-between items-center p-3 border-b border-base-300 hover:bg-base-200 ${item.unread ? "bg-primary/5" : ""}`, class: `flex justify-between items-center p-3 border-b border-base-300 hover:bg-base-200 ${item.unread ? "bg-primary/5" : ""}`,
}, },
[ [
Div({ class: "flex-1" }, [ div({ class: "flex-1" }, [
Div({ class: "font-medium" }, item.message), div({ class: "font-medium" }, item.message),
Div({ class: "text-xs opacity-50" }, item.time), div({ class: "text-xs opacity-50" }, item.time),
]), ]),
item.unread item.unread
? Span({ class: "badge badge-primary badge-sm" }, "New") ? span({ class: "badge badge-primary badge-sm" }, "New")
: null, : null,
], ],
), ),
@@ -223,19 +223,19 @@ const InteractiveDemo = () => {
Review: "badge-accent", Review: "badge-accent",
}; };
return Div({ class: "flex flex-col gap-4" }, [ return div({ class: "flex flex-col gap-4" }, [
List({ List({
items: items, items: items,
render: (item) => render: (item) =>
Div( div(
{ {
class: `p-3 cursor-pointer transition-all hover:bg-base-200 ${selected() === item.id ? "bg-primary/10 border-l-4 border-primary" : "border-l-4 border-transparent"}`, class: `p-3 cursor-pointer transition-all hover:bg-base-200 ${selected() === item.id ? "bg-primary/10 border-l-4 border-primary" : "border-l-4 border-transparent"}`,
onclick: () => selected(item.id), onclick: () => selected(item.id),
}, },
[ [
Div({ class: "flex justify-between items-center" }, [ div({ class: "flex justify-between items-center" }, [
Div({ class: "font-medium" }, item.name), div({ class: "font-medium" }, item.name),
Span( span(
{ class: `badge ${statusColors[item.status]}` }, { class: `badge ${statusColors[item.status]}` },
item.status, item.status,
), ),
@@ -245,11 +245,11 @@ const InteractiveDemo = () => {
}), }),
() => () =>
selected() selected()
? Div( ? div(
{ class: "alert alert-info" }, { class: "alert alert-info" },
`Selected: ${items.find((i) => i.id === selected()).name}`, `Selected: ${items.find((i) => i.id === selected()).name}`,
) )
: Div({ class: "alert alert-soft" }, "Select a project to see details"), : div({ class: "alert alert-soft" }, "Select a project to see details"),
]); ]);
}; };
mount(InteractiveDemo, "#demo-interactive"); mount(InteractiveDemo, "#demo-interactive");
@@ -292,15 +292,15 @@ const ReactiveDemo = () => {
const pendingCount = () => todos().filter(t => !t.done).length; const pendingCount = () => todos().filter(t => !t.done).length;
watch(()=> console.log(pendingCount())); watch(()=> console.log(pendingCount()));
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex gap-2' }, [ div({ class: 'flex gap-2' }, [
Input({ input({
placeholder: 'Add new task...', placeholder: 'Add new task...',
value: newTodo, value: newTodo,
oninput: (e) => newTodo(e.target.value), oninput: (e) => newTodo(e.target.value),
onkeypress: (e) => e.key === 'Enter' && addTodo() onkeypress: (e) => e.key === 'Enter' && addTodo()
}), }),
Button({ class: 'btn btn-primary', onclick: addTodo }, 'Add') button({ class: 'btn btn-primary', onclick: addTodo }, 'Add')
]), ]),
List({ List({
items: todos, items: todos,
@@ -308,25 +308,25 @@ const ReactiveDemo = () => {
// Esta función busca siempre el estado actual del item dentro del signal // Esta función busca siempre el estado actual del item dentro del signal
const it = () => todos().find(t => t.id === item.id) || item; const it = () => todos().find(t => t.id === item.id) || item;
return Div({ return div({
class: () => `flex items-center gap-3 p-2 border-b border-base-300 ${it().done ? 'opacity-60' : ''}` class: () => `flex items-center gap-3 p-2 border-b border-base-300 ${it().done ? 'opacity-60' : ''}`
}, [ }, [
Checkbox({ Checkbox({
value: () => it().done, value: () => it().done,
onclick: () => toggleTodo(item.id) onclick: () => toggleTodo(item.id)
}), }),
Span({ span({
class: () => `flex-1 ${it().done ? 'line-through' : ''}`, class: () => `flex-1 ${it().done ? 'line-through' : ''}`,
onclick: () => toggleTodo(item.id) onclick: () => toggleTodo(item.id)
}, () => it().text), }, () => it().text),
Button({ button({
class: 'btn btn-ghost btn-xs btn-circle', class: 'btn btn-ghost btn-xs btn-circle',
onclick: () => deleteTodo(item.id) onclick: () => deleteTodo(item.id)
}, '✕') }, '✕')
]); ]);
} }
}), }),
Div({ class: 'text-sm opacity-70 mt-2' }, () => `${pendingCount()} tasks remaining`) div({ class: 'text-sm opacity-70 mt-2' }, () => `${pendingCount()} tasks remaining`)
]); ]);
}; };
@@ -354,14 +354,14 @@ const AvatarDemo = () => {
return List({ return List({
items: contacts, items: contacts,
render: (contact) => render: (contact) =>
Div({ class: "flex gap-3 p-3 hover:bg-base-200 transition-colors" }, [ div({ class: "flex gap-3 p-3 hover:bg-base-200 transition-colors" }, [
Div( div(
{ {
class: `avatar ${contact.online ? "online" : "offline"}`, class: `avatar ${contact.online ? "online" : "offline"}`,
style: "width: 48px", style: "width: 48px",
}, },
[ [
Div( div(
{ {
class: class:
"rounded-full bg-primary text-primary-content flex items-center justify-center w-12 h-12 font-bold", "rounded-full bg-primary text-primary-content flex items-center justify-center w-12 h-12 font-bold",
@@ -370,11 +370,11 @@ const AvatarDemo = () => {
), ),
], ],
), ),
Div({ class: "flex-1" }, [ div({ class: "flex-1" }, [
Div({ class: "font-medium" }, contact.name), div({ class: "font-medium" }, contact.name),
Div({ class: "text-sm opacity-60" }, contact.role), div({ class: "text-sm opacity-60" }, contact.role),
]), ]),
Div( div(
{ {
class: `badge badge-sm ${contact.online ? "badge-success" : "badge-ghost"}`, class: `badge badge-sm ${contact.online ? "badge-success" : "badge-ghost"}`,
}, },
@@ -399,24 +399,24 @@ mount(AvatarDemo, "#demo-avatar");
const VariantsDemo = () => { const VariantsDemo = () => {
const items = ["Item 1", "Item 2", "Item 3"]; const items = ["Item 1", "Item 2", "Item 3"];
return Div({ class: "flex flex-col gap-6" }, [ return div({ class: "flex flex-col gap-6" }, [
Div({ class: "text-sm font-bold" }, "Default List"), div({ class: "text-sm font-bold" }, "Default List"),
List({ List({
items: items, items: items,
render: (item) => Div({ class: "p-2" }, item), render: (item) => div({ class: "p-2" }, item),
}), }),
Div({ class: "text-sm font-bold mt-2" }, "With Shadow"), div({ class: "text-sm font-bold mt-2" }, "With Shadow"),
List({ List({
items: items, items: items,
render: (item) => Div({ class: "p-2" }, item), render: (item) => div({ class: "p-2" }, item),
class: "shadow-lg", class: "shadow-lg",
}), }),
Div({ class: "text-sm font-bold mt-2" }, "Rounded Corners"), div({ class: "text-sm font-bold mt-2" }, "Rounded Corners"),
List({ List({
items: items, items: items,
render: (item) => Div({ class: "p-2" }, item), render: (item) => div({ class: "p-2" }, item),
class: "rounded-box overflow-hidden", class: "rounded-box overflow-hidden",
}), }),
]); ]);

View File

@@ -248,8 +248,8 @@ mount(HorizontalDemo, '#demo-horizontal');
const SidebarDemo = () => { const SidebarDemo = () => {
const activeItem = $('dashboard'); const activeItem = $('dashboard');
return Div({ class: 'flex' }, [ return div({ class: 'flex' }, [
Div({ class: 'w-64' }, [ div({ class: 'w-64' }, [
Menu({ Menu({
class: 'rounded-box w-full', class: 'rounded-box w-full',
items: [ items: [
@@ -290,8 +290,8 @@ const SidebarDemo = () => {
] ]
}) })
]), ]),
Div({ class: 'flex-1 p-4' }, [ div({ class: 'flex-1 p-4' }, [
Div({ class: 'alert alert-info' }, () => `Current page: ${activeItem()}`) div({ class: 'alert alert-info' }, () => `Current page: ${activeItem()}`)
]) ])
]); ]);
}; };
@@ -363,9 +363,9 @@ const CollapsibleDemo = () => {
const collapsed = $(false); const collapsed = $(false);
const activeItem = $('dashboard'); const activeItem = $('dashboard');
return Div({ class: 'flex gap-4' }, [ return div({ class: 'flex gap-4' }, [
Div({ class: `transition-all duration-300 ${collapsed() ? 'w-16' : 'w-64'}` }, [ div({ class: `transition-all duration-300 ${collapsed() ? 'w-16' : 'w-64'}` }, [
Button({ button({
class: 'btn btn-ghost btn-sm mb-2 w-full', class: 'btn btn-ghost btn-sm mb-2 w-full',
onclick: () => collapsed(!collapsed()) onclick: () => collapsed(!collapsed())
}, collapsed() ? '→' : '←'), }, collapsed() ? '→' : '←'),
@@ -379,8 +379,8 @@ const CollapsibleDemo = () => {
] ]
}) })
]), ]),
Div({ class: 'flex-1' }, [ div({ class: 'flex-1' }, [
Div({ class: 'alert alert-info' }, () => `Selected: ${activeItem()}`) div({ class: 'alert alert-info' }, () => `Selected: ${activeItem()}`)
]) ])
]); ]);
}; };
@@ -407,17 +407,17 @@ const VariantsDemo = () => {
]} ]}
]; ];
return Div({ class: 'flex flex-wrap gap-8' }, [ return div({ class: 'flex flex-wrap gap-8' }, [
Div({ class: 'w-48' }, [ div({ class: 'w-48' }, [
Div({ class: 'text-sm font-bold mb-2' }, 'Default'), div({ class: 'text-sm font-bold mb-2' }, 'Default'),
Menu({ items }) Menu({ items })
]), ]),
Div({ class: 'w-48' }, [ div({ class: 'w-48' }, [
Div({ class: 'text-sm font-bold mb-2' }, 'Compact'), div({ class: 'text-sm font-bold mb-2' }, 'Compact'),
Menu({ items, class: 'menu-compact' }) Menu({ items, class: 'menu-compact' })
]), ]),
Div({ class: 'w-48' }, [ div({ class: 'w-48' }, [
Div({ class: 'text-sm font-bold mb-2' }, 'With Shadow'), div({ class: 'text-sm font-bold mb-2' }, 'With Shadow'),
Menu({ items, class: 'shadow-lg' }) Menu({ items, class: 'shadow-lg' })
]) ])
]); ]);

View File

@@ -42,8 +42,8 @@ Modal supports all **daisyUI Modal classes**:
const BasicDemo = () => { const BasicDemo = () => {
const isOpen = $(false); const isOpen = $(false);
return Div({ class: 'flex justify-center' }, [ return div({ class: 'flex justify-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => { onclick: () => {
isOpen(true); isOpen(true);
@@ -52,14 +52,14 @@ const BasicDemo = () => {
Modal({ Modal({
open: isOpen, open: isOpen,
title: 'Basic Modal', title: 'Basic Modal',
buttons: Button({ buttons: button({
class: 'btn-primary', class: 'btn-primary',
onclick: () => { onclick: () => {
isOpen(false); isOpen(false);
} }
}, 'Custom Action') }, 'Custom Action')
}, [ }, [
Div({ class: 'py-4' }, 'This is a basic modal dialog. Press ESC or click Close.') div({ class: 'py-4' }, 'This is a basic modal dialog. Press ESC or click Close.')
]) ])
]); ]);
}; };
@@ -103,8 +103,8 @@ const ActionsDemo = () => {
Toast('Action confirmed!', 'alert-success', 2000); Toast('Action confirmed!', 'alert-success', 2000);
}; };
return Div({ class: 'flex flex-col gap-4 items-center' }, [ return div({ class: 'flex flex-col gap-4 items-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, 'Confirm Action'), }, 'Confirm Action'),
@@ -116,17 +116,17 @@ const ActionsDemo = () => {
open: isOpen, open: isOpen,
title: 'Confirm Action', title: 'Confirm Action',
buttons: [ buttons: [
Button({ button({
class: 'btn btn-ghost', class: 'btn btn-ghost',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, 'Cancel'), }, 'Cancel'),
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: handleConfirm onclick: handleConfirm
}, 'Confirm') }, 'Confirm')
] ]
}, [ }, [
Div({ class: 'py-4' }, 'Are you sure you want to perform this action? This cannot be undone.') div({ class: 'py-4' }, 'Are you sure you want to perform this action? This cannot be undone.')
]) ])
]); ]);
}; };
@@ -158,8 +158,8 @@ const FormModal = () => {
} }
}; };
return Div({ class: 'flex flex-col gap-4 items-center' }, [ return div({ class: 'flex flex-col gap-4 items-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, 'Sign Up'), }, 'Sign Up'),
@@ -171,24 +171,24 @@ const FormModal = () => {
open: isOpen, open: isOpen,
title: 'Create Account', title: 'Create Account',
buttons: [ buttons: [
Button({ button({
class: 'btn btn-ghost', class: 'btn btn-ghost',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, 'Cancel'), }, 'Cancel'),
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: handleSubmit onclick: handleSubmit
}, 'Sign Up') }, 'Sign Up')
] ]
}, [ }, [
Div({ class: 'flex flex-col gap-4 py-2' }, [ div({ class: 'flex flex-col gap-4 py-2' }, [
Input({ input({
label: 'Full Name', label: 'Full Name',
value: name, value: name,
placeholder: 'Enter your name', placeholder: 'Enter your name',
oninput: (e) => name(e.target.value) oninput: (e) => name(e.target.value)
}), }),
Input({ input({
label: 'Email', label: 'Email',
type: 'email', type: 'email',
value: email, value: email,
@@ -232,11 +232,11 @@ const ConfirmDemo = () => {
Toast(`Deleted: ${pendingDelete().name}`, 'alert-info', 2000); Toast(`Deleted: ${pendingDelete().name}`, 'alert-info', 2000);
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex flex-col gap-2' }, items().map(item => div({ class: 'flex flex-col gap-2' }, items().map(item =>
Div({ class: 'flex justify-between items-center p-3 bg-base-200 rounded-lg' }, [ div({ class: 'flex justify-between items-center p-3 bg-base-200 rounded-lg' }, [
Span({}, item.name), span({}, item.name),
Button({ button({
class: 'btn btn-xs btn-error', class: 'btn btn-xs btn-error',
onclick: () => confirmDelete(item) onclick: () => confirmDelete(item)
}, 'Delete') }, 'Delete')
@@ -246,17 +246,17 @@ const ConfirmDemo = () => {
open: isOpen, open: isOpen,
title: 'Delete Confirmation', title: 'Delete Confirmation',
buttons: [ buttons: [
Button({ button({
class: 'btn btn-ghost', class: 'btn btn-ghost',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, 'Cancel'), }, 'Cancel'),
Button({ button({
class: 'btn btn-error', class: 'btn btn-error',
onclick: handleDelete onclick: handleDelete
}, 'Delete') }, 'Delete')
] ]
}, [ }, [
Div({ class: 'py-4' }, () => `Are you sure you want to delete "${pendingDelete()?.name}"? This action cannot be undone.`) div({ class: 'py-4' }, () => `Are you sure you want to delete "${pendingDelete()?.name}"? This action cannot be undone.`)
]) ])
]); ]);
}; };
@@ -276,35 +276,35 @@ mount(ConfirmDemo, '#demo-confirm');
const LargeDemo = () => { const LargeDemo = () => {
const isOpen = $(false); const isOpen = $(false);
return Div({ class: 'flex justify-center' }, [ return div({ class: 'flex justify-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, 'Open Large Modal'), }, 'Open Large Modal'),
Modal({ Modal({
open: isOpen, open: isOpen,
title: 'Terms and Conditions', title: 'Terms and Conditions',
buttons: Button({ buttons: button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, 'I Agree') }, 'I Agree')
}, [ }, [
Div({ class: 'py-4 max-h-96 overflow-y-auto' }, [ div({ class: 'py-4 max-h-96 overflow-y-auto' }, [
Div({ class: 'space-y-4' }, [ div({ class: 'space-y-4' }, [
Div({ class: 'text-sm' }, [ div({ class: 'text-sm' }, [
Div({ class: 'font-bold mb-2' }, '1. Introduction'), div({ class: 'font-bold mb-2' }, '1. Introduction'),
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.' 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.'
]), ]),
Div({ class: 'text-sm' }, [ div({ class: 'text-sm' }, [
Div({ class: 'font-bold mb-2' }, '2. User Obligations'), div({ class: 'font-bold mb-2' }, '2. User Obligations'),
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.' 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.'
]), ]),
Div({ class: 'text-sm' }, [ div({ class: 'text-sm' }, [
Div({ class: 'font-bold mb-2' }, '3. Privacy Policy'), div({ class: 'font-bold mb-2' }, '3. Privacy Policy'),
'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.' 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.'
]), ]),
Div({ class: 'text-sm' }, [ div({ class: 'text-sm' }, [
Div({ class: 'font-bold mb-2' }, '4. Termination'), div({ class: 'font-bold mb-2' }, '4. Termination'),
'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores.' 'At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores.'
]) ])
]) ])
@@ -330,27 +330,27 @@ const MultipleDemo = () => {
const modal2 = $(false); const modal2 = $(false);
const modal3 = $(false); const modal3 = $(false);
return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [ return div({ class: 'flex flex-wrap gap-4 justify-center' }, [
Button({ class: 'btn', onclick: () => modal1(true) }, 'Info Modal'), button({ class: 'btn', onclick: () => modal1(true) }, 'Info Modal'),
Button({ class: 'btn', onclick: () => modal2(true) }, 'Success Modal'), button({ class: 'btn', onclick: () => modal2(true) }, 'Success Modal'),
Button({ class: 'btn', onclick: () => modal3(true) }, 'Warning Modal'), button({ class: 'btn', onclick: () => modal3(true) }, 'Warning Modal'),
Modal({ Modal({
open: modal1, open: modal1,
title: 'Information', title: 'Information',
buttons: Button({ onclick: () => modal1(false) }, 'OK') buttons: button({ onclick: () => modal1(false) }, 'OK')
}, 'This is an informational message.'), }, 'This is an informational message.'),
Modal({ Modal({
open: modal2, open: modal2,
title: 'Success!', title: 'Success!',
buttons: Button({ onclick: () => modal2(false) }, 'Great!') buttons: button({ onclick: () => modal2(false) }, 'Great!')
}, 'Your operation was completed successfully.'), }, 'Your operation was completed successfully.'),
Modal({ Modal({
open: modal3, open: modal3,
title: 'Warning', title: 'Warning',
buttons: Button({ onclick: () => modal3(false) }, 'Understood') buttons: button({ onclick: () => modal3(false) }, 'Understood')
}, 'Please review your input before proceeding.') }, 'Please review your input before proceeding.')
]); ]);
}; };
@@ -370,8 +370,8 @@ mount(MultipleDemo, '#demo-multiple');
const CustomDemo = () => { const CustomDemo = () => {
const isOpen = $(false); const isOpen = $(false);
return Div({ class: 'flex justify-center' }, [ return div({ class: 'flex justify-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => isOpen(true) onclick: () => isOpen(true)
}, 'Open Custom Modal'), }, 'Open Custom Modal'),
@@ -379,11 +379,11 @@ const CustomDemo = () => {
open: isOpen, open: isOpen,
class: 'bg-gradient-to-r from-primary to-secondary text-primary-content' class: 'bg-gradient-to-r from-primary to-secondary text-primary-content'
}, [ }, [
Div({ class: 'text-center py-8' }, [ div({ class: 'text-center py-8' }, [
Div({ class: 'text-6xl mb-4' }, '🎉'), div({ class: 'text-6xl mb-4' }, '🎉'),
Div({ class: 'text-2xl font-bold mb-2' }, 'Congratulations!'), div({ class: 'text-2xl font-bold mb-2' }, 'Congratulations!'),
Div({ class: 'mb-6' }, 'You\'ve successfully completed the tutorial.'), div({ class: 'mb-6' }, 'You\'ve successfully completed the tutorial.'),
Button({ button({
class: 'btn btn-ghost bg-white/20 hover:bg-white/30', class: 'btn btn-ghost bg-white/20 hover:bg-white/30',
onclick: () => isOpen(false) onclick: () => isOpen(false)
}, 'Get Started') }, 'Get Started')

View File

@@ -40,14 +40,14 @@ Navbar supports all **daisyUI Navbar classes**:
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Navbar({ class: 'rounded-box' }, [ return Navbar({ class: 'rounded-box' }, [
Div({ class: 'navbar-start' }, [ div({ class: 'navbar-start' }, [
Span({ class: 'text-xl font-bold' }, 'Logo') span({ class: 'text-xl font-bold' }, 'Logo')
]), ]),
Div({ class: 'navbar-center hidden lg:flex' }, [ div({ class: 'navbar-center hidden lg:flex' }, [
Span({ class: 'text-sm' }, 'Navigation Items') span({ class: 'text-sm' }, 'Navigation Items')
]), ]),
Div({ class: 'navbar-end' }, [ div({ class: 'navbar-end' }, [
Button({ class: 'btn btn-ghost btn-sm' }, 'Login') button({ class: 'btn btn-ghost btn-sm' }, 'Login')
]) ])
]); ]);
}; };
@@ -68,27 +68,27 @@ const LinksDemo = () => {
const active = $('home'); const active = $('home');
return Navbar({ class: 'rounded-box' }, [ return Navbar({ class: 'rounded-box' }, [
Div({ class: 'navbar-start' }, [ div({ class: 'navbar-start' }, [
Span({ class: 'text-xl font-bold' }, 'MyApp') span({ class: 'text-xl font-bold' }, 'MyApp')
]), ]),
Div({ class: 'navbar-center hidden lg:flex' }, [ div({ class: 'navbar-center hidden lg:flex' }, [
Div({ class: 'menu menu-horizontal px-1' }, [ div({ class: 'menu menu-horizontal px-1' }, [
Button({ button({
class: `btn btn-ghost btn-sm ${active() === 'home' ? 'btn-active' : ''}`, class: `btn btn-ghost btn-sm ${active() === 'home' ? 'btn-active' : ''}`,
onclick: () => active('home') onclick: () => active('home')
}, 'Home'), }, 'Home'),
Button({ button({
class: `btn btn-ghost btn-sm ${active() === 'about' ? 'btn-active' : ''}`, class: `btn btn-ghost btn-sm ${active() === 'about' ? 'btn-active' : ''}`,
onclick: () => active('about') onclick: () => active('about')
}, 'About'), }, 'About'),
Button({ button({
class: `btn btn-ghost btn-sm ${active() === 'contact' ? 'btn-active' : ''}`, class: `btn btn-ghost btn-sm ${active() === 'contact' ? 'btn-active' : ''}`,
onclick: () => active('contact') onclick: () => active('contact')
}, 'Contact') }, 'Contact')
]) ])
]), ]),
Div({ class: 'navbar-end' }, [ div({ class: 'navbar-end' }, [
Button({ class: 'btn btn-primary btn-sm' }, 'Sign Up') button({ class: 'btn btn-primary btn-sm' }, 'Sign Up')
]) ])
]); ]);
}; };
@@ -109,12 +109,12 @@ const SearchDemo = () => {
const searchQuery = $(''); const searchQuery = $('');
return Navbar({ class: 'rounded-box' }, [ return Navbar({ class: 'rounded-box' }, [
Div({ class: 'navbar-start' }, [ div({ class: 'navbar-start' }, [
Span({ class: 'text-xl font-bold' }, 'MyApp') span({ class: 'text-xl font-bold' }, 'MyApp')
]), ]),
Div({ class: 'navbar-center' }, [ div({ class: 'navbar-center' }, [
Div({ class: 'form-control' }, [ div({ class: 'form-control' }, [
Input({ input({
placeholder: 'Search...', placeholder: 'Search...',
value: searchQuery, value: searchQuery,
class: 'input input-bordered w-48 md:w-auto', class: 'input input-bordered w-48 md:w-auto',
@@ -122,9 +122,9 @@ const SearchDemo = () => {
}) })
]) ])
]), ]),
Div({ class: 'navbar-end' }, [ div({ class: 'navbar-end' }, [
Button({ class: 'btn btn-ghost btn-circle' }, '🔔'), button({ class: 'btn btn-ghost btn-circle' }, '🔔'),
Button({ class: 'btn btn-ghost btn-circle' }, '👤') button({ class: 'btn btn-ghost btn-circle' }, '👤')
]) ])
]); ]);
}; };
@@ -143,25 +143,25 @@ mount(SearchDemo, '#demo-search');
```javascript ```javascript
const AvatarDemo = () => { const AvatarDemo = () => {
return Navbar({ class: 'rounded-box' }, [ return Navbar({ class: 'rounded-box' }, [
Div({ class: 'navbar-start' }, [ div({ class: 'navbar-start' }, [
Span({ class: 'text-xl font-bold' }, 'MyApp') span({ class: 'text-xl font-bold' }, 'MyApp')
]), ]),
Div({ class: 'navbar-center hidden lg:flex' }, [ div({ class: 'navbar-center hidden lg:flex' }, [
Div({ class: 'menu menu-horizontal px-1' }, [ div({ class: 'menu menu-horizontal px-1' }, [
Span({ class: 'text-sm' }, 'Dashboard'), span({ class: 'text-sm' }, 'Dashboard'),
Span({ class: 'text-sm' }, 'Projects'), span({ class: 'text-sm' }, 'Projects'),
Span({ class: 'text-sm' }, 'Tasks') span({ class: 'text-sm' }, 'Tasks')
]) ])
]), ]),
Div({ class: 'navbar-end' }, [ div({ class: 'navbar-end' }, [
Div({ class: 'dropdown dropdown-end' }, [ div({ class: 'dropdown dropdown-end' }, [
Div({ tabindex: 0, role: 'button', class: 'btn btn-ghost btn-circle avatar' }, [ div({ tabindex: 0, role: 'button', class: 'btn btn-ghost btn-circle avatar' }, [
Div({ class: 'w-8 rounded-full bg-primary text-primary-content flex items-center justify-center' }, 'JD') div({ class: 'w-8 rounded-full bg-primary text-primary-content flex items-center justify-center' }, 'JD')
]), ]),
Div({ tabindex: 0, class: 'dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow' }, [ div({ tabindex: 0, class: 'dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow' }, [
Span({ class: 'menu-item' }, 'Profile'), span({ class: 'menu-item' }, 'Profile'),
Span({ class: 'menu-item' }, 'Settings'), span({ class: 'menu-item' }, 'Settings'),
Span({ class: 'menu-item' }, 'Logout') span({ class: 'menu-item' }, 'Logout')
]) ])
]) ])
]) ])
@@ -183,26 +183,26 @@ mount(AvatarDemo, '#demo-avatar');
const ResponsiveDemo = () => { const ResponsiveDemo = () => {
const isOpen = $(false); const isOpen = $(false);
return Div({ class: 'flex flex-col' }, [ return div({ class: 'flex flex-col' }, [
Navbar({ class: 'rounded-box' }, [ Navbar({ class: 'rounded-box' }, [
Div({ class: 'navbar-start' }, [ div({ class: 'navbar-start' }, [
Button({ button({
class: 'btn btn-ghost btn-circle lg:hidden', class: 'btn btn-ghost btn-circle lg:hidden',
onclick: () => isOpen(!isOpen()) onclick: () => isOpen(!isOpen())
}, '☰') }, '☰')
]), ]),
Div({ class: 'navbar-center' }, [ div({ class: 'navbar-center' }, [
Span({ class: 'text-xl font-bold' }, 'MyApp') span({ class: 'text-xl font-bold' }, 'MyApp')
]), ]),
Div({ class: 'navbar-end' }, [ div({ class: 'navbar-end' }, [
Button({ class: 'btn btn-ghost btn-circle' }, '🔔') button({ class: 'btn btn-ghost btn-circle' }, '🔔')
]) ])
]), ]),
() => isOpen() ? Div({ class: 'flex flex-col gap-2 p-4 bg-base-200 rounded-box mt-2' }, [ () => isOpen() ? div({ class: 'flex flex-col gap-2 p-4 bg-base-200 rounded-box mt-2' }, [
Button({ class: 'btn btn-ghost justify-start' }, 'Home'), button({ class: 'btn btn-ghost justify-start' }, 'Home'),
Button({ class: 'btn btn-ghost justify-start' }, 'About'), button({ class: 'btn btn-ghost justify-start' }, 'About'),
Button({ class: 'btn btn-ghost justify-start' }, 'Services'), button({ class: 'btn btn-ghost justify-start' }, 'Services'),
Button({ class: 'btn btn-ghost justify-start' }, 'Contact') button({ class: 'btn btn-ghost justify-start' }, 'Contact')
]) : null ]) : null
]); ]);
}; };
@@ -221,19 +221,19 @@ mount(ResponsiveDemo, '#demo-responsive');
```javascript ```javascript
const BrandDemo = () => { const BrandDemo = () => {
return Navbar({ class: 'rounded-box bg-primary text-primary-content' }, [ return Navbar({ class: 'rounded-box bg-primary text-primary-content' }, [
Div({ class: 'navbar-start' }, [ div({ class: 'navbar-start' }, [
Span({ class: 'text-xl font-bold' }, 'Brand') span({ class: 'text-xl font-bold' }, 'Brand')
]), ]),
Div({ class: 'navbar-center hidden lg:flex' }, [ div({ class: 'navbar-center hidden lg:flex' }, [
Div({ class: 'menu menu-horizontal px-1' }, [ div({ class: 'menu menu-horizontal px-1' }, [
Span({ class: 'text-sm' }, 'Features'), span({ class: 'text-sm' }, 'Features'),
Span({ class: 'text-sm' }, 'Pricing'), span({ class: 'text-sm' }, 'Pricing'),
Span({ class: 'text-sm' }, 'About') span({ class: 'text-sm' }, 'About')
]) ])
]), ]),
Div({ class: 'navbar-end' }, [ div({ class: 'navbar-end' }, [
Button({ class: 'btn btn-ghost btn-sm' }, 'Login'), button({ class: 'btn btn-ghost btn-sm' }, 'Login'),
Button({ class: 'btn btn-outline btn-sm ml-2' }, 'Sign Up') button({ class: 'btn btn-outline btn-sm ml-2' }, 'Sign Up')
]) ])
]); ]);
}; };
@@ -251,24 +251,24 @@ mount(BrandDemo, '#demo-brand');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-sm font-bold' }, 'Default Navbar'), div({ class: 'text-sm font-bold' }, 'Default Navbar'),
Navbar({ class: 'rounded-box' }, [ Navbar({ class: 'rounded-box' }, [
Div({ class: 'navbar-start' }, [Span({}, 'Start')]), div({ class: 'navbar-start' }, [span({}, 'Start')]),
Div({ class: 'navbar-center' }, [Span({}, 'Center')]), div({ class: 'navbar-center' }, [span({}, 'Center')]),
Div({ class: 'navbar-end' }, [Span({}, 'End')]) div({ class: 'navbar-end' }, [span({}, 'End')])
]), ]),
Div({ class: 'text-sm font-bold mt-2' }, 'With Shadow'), div({ class: 'text-sm font-bold mt-2' }, 'With Shadow'),
Navbar({ class: 'rounded-box shadow-lg' }, [ Navbar({ class: 'rounded-box shadow-lg' }, [
Div({ class: 'navbar-start' }, [Span({}, 'Logo')]), div({ class: 'navbar-start' }, [span({}, 'Logo')]),
Div({ class: 'navbar-end' }, [Button({ class: 'btn btn-sm' }, 'Button')]) div({ class: 'navbar-end' }, [button({ class: 'btn btn-sm' }, 'Button')])
]), ]),
Div({ class: 'text-sm font-bold mt-2' }, 'With Background'), div({ class: 'text-sm font-bold mt-2' }, 'With Background'),
Navbar({ class: 'rounded-box bg-base-300' }, [ Navbar({ class: 'rounded-box bg-base-300' }, [
Div({ class: 'navbar-start' }, [Span({ class: 'font-bold' }, 'Colored')]), div({ class: 'navbar-start' }, [span({ class: 'font-bold' }, 'Colored')]),
Div({ class: 'navbar-end' }, [Span({ class: 'text-sm' }, 'Info')]) div({ class: 'navbar-end' }, [span({ class: 'text-sm' }, 'Info')])
]) ])
]); ]);
}; };

View File

@@ -45,7 +45,7 @@ Radio supports all **daisyUI Radio classes**:
const BasicDemo = () => { const BasicDemo = () => {
const selected = $('option1'); const selected = $('option1');
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Radio({ Radio({
label: 'Option 1', label: 'Option 1',
name: 'basic-group', name: 'basic-group',
@@ -67,7 +67,7 @@ const BasicDemo = () => {
inputValue: 'option3', inputValue: 'option3',
onclick: () => selected('option3') onclick: () => selected('option3')
}), }),
Div({ class: 'mt-2 text-sm opacity-70' }, () => `Selected: ${selected()}`) div({ class: 'mt-2 text-sm opacity-70' }, () => `Selected: ${selected()}`)
]); ]);
}; };
mount(BasicDemo, '#demo-basic'); mount(BasicDemo, '#demo-basic');
@@ -86,7 +86,7 @@ mount(BasicDemo, '#demo-basic');
const TooltipDemo = () => { const TooltipDemo = () => {
const selected = $('light'); const selected = $('light');
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Radio({ Radio({
label: 'Light mode', label: 'Light mode',
name: 'theme-group', name: 'theme-group',
@@ -121,7 +121,7 @@ mount(TooltipDemo, '#demo-tooltip');
const DisabledDemo = () => { const DisabledDemo = () => {
const selected = $('enabled'); const selected = $('enabled');
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Radio({ Radio({
label: 'Enabled option', label: 'Enabled option',
name: 'disabled-group', name: 'disabled-group',
@@ -168,9 +168,9 @@ const ReactiveDemo = () => {
{ value: 'red', label: 'Red' } { value: 'red', label: 'Red' }
]; ];
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-sm font-bold' }, 'Select size'), div({ class: 'text-sm font-bold' }, 'Select size'),
Div({ class: 'flex gap-4' }, sizes.map(s => div({ class: 'flex gap-4' }, sizes.map(s =>
Radio({ Radio({
label: s.label, label: s.label,
name: 'size-group', name: 'size-group',
@@ -179,8 +179,8 @@ const ReactiveDemo = () => {
onclick: () => size(s.value) onclick: () => size(s.value)
}) })
)), )),
Div({ class: 'text-sm font-bold mt-2' }, 'Select color'), div({ class: 'text-sm font-bold mt-2' }, 'Select color'),
Div({ class: 'flex gap-4' }, colors.map(c => div({ class: 'flex gap-4' }, colors.map(c =>
Radio({ Radio({
label: c.label, label: c.label,
name: 'color-group', name: 'color-group',
@@ -189,7 +189,7 @@ const ReactiveDemo = () => {
onclick: () => color(c.value) onclick: () => color(c.value)
}) })
)), )),
Div({ div({
class: 'mt-4 p-4 rounded-lg text-center transition-all', class: 'mt-4 p-4 rounded-lg text-center transition-all',
style: () => { style: () => {
const sizeMap = { small: 'text-sm', medium: 'text-base', large: 'text-lg' }; const sizeMap = { small: 'text-sm', medium: 'text-base', large: 'text-lg' };
@@ -215,9 +215,9 @@ mount(ReactiveDemo, '#demo-reactive');
const PaymentDemo = () => { const PaymentDemo = () => {
const method = $('credit'); const method = $('credit');
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-sm font-bold' }, 'Payment method'), div({ class: 'text-sm font-bold' }, 'Payment method'),
Div({ class: 'flex flex-col gap-3' }, [ div({ class: 'flex flex-col gap-3' }, [
Radio({ Radio({
label: '💳 Credit Card', label: '💳 Credit Card',
name: 'payment-group', name: 'payment-group',
@@ -240,7 +240,7 @@ const PaymentDemo = () => {
onclick: () => method('wallet') onclick: () => method('wallet')
}) })
]), ]),
Div({ class: 'alert alert-info mt-2' }, () => { div({ class: 'alert alert-info mt-2' }, () => {
const messages = { const messages = {
credit: 'You selected Credit Card. Enter your card details.', credit: 'You selected Credit Card. Enter your card details.',
bank: 'You selected Bank Transfer. Use the provided account number.', bank: 'You selected Bank Transfer. Use the provided account number.',
@@ -268,10 +268,10 @@ const VariantsDemo = () => {
const secondary = $('secondary1'); const secondary = $('secondary1');
const accent = $('accent1'); const accent = $('accent1');
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'card bg-base-200 p-4' }, [ div({ class: 'card bg-base-200 p-4' }, [
Div({ class: 'text-sm font-bold mb-2' }, 'Primary variant'), div({ class: 'text-sm font-bold mb-2' }, 'Primary variant'),
Div({ class: 'flex gap-4' }, [ div({ class: 'flex gap-4' }, [
Radio({ Radio({
label: 'Option A', label: 'Option A',
name: 'primary-group', name: 'primary-group',
@@ -290,9 +290,9 @@ const VariantsDemo = () => {
}) })
]) ])
]), ]),
Div({ class: 'card bg-base-200 p-4' }, [ div({ class: 'card bg-base-200 p-4' }, [
Div({ class: 'text-sm font-bold mb-2' }, 'Secondary variant'), div({ class: 'text-sm font-bold mb-2' }, 'Secondary variant'),
Div({ class: 'flex gap-4' }, [ div({ class: 'flex gap-4' }, [
Radio({ Radio({
label: 'Option A', label: 'Option A',
name: 'secondary-group', name: 'secondary-group',
@@ -311,9 +311,9 @@ const VariantsDemo = () => {
}) })
]) ])
]), ]),
Div({ class: 'card bg-base-200 p-4' }, [ div({ class: 'card bg-base-200 p-4' }, [
Div({ class: 'text-sm font-bold mb-2' }, 'Accent variant'), div({ class: 'text-sm font-bold mb-2' }, 'Accent variant'),
Div({ class: 'flex gap-4' }, [ div({ class: 'flex gap-4' }, [
Radio({ Radio({
label: 'Option A', label: 'Option A',
name: 'accent-group', name: 'accent-group',
@@ -364,8 +364,8 @@ const DynamicDemo = () => {
] ]
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex gap-4' }, [ div({ class: 'flex gap-4' }, [
Radio({ Radio({
label: 'Cars', label: 'Cars',
name: 'category-group', name: 'category-group',
@@ -387,9 +387,9 @@ const DynamicDemo = () => {
} }
}) })
]), ]),
Div({ class: 'divider my-1' }), div({ class: 'divider my-1' }),
Div({ class: 'text-sm font-bold' }, () => `Select ${category()}`), div({ class: 'text-sm font-bold' }, () => `Select ${category()}`),
Div({ class: 'flex flex-col gap-2' }, () => div({ class: 'flex flex-col gap-2' }, () =>
options[category()].map(opt => options[category()].map(opt =>
Radio({ Radio({
label: opt.label, label: opt.label,
@@ -401,7 +401,7 @@ const DynamicDemo = () => {
) )
), ),
() => selected() () => selected()
? Div({ class: 'alert alert-success mt-2' }, () => `Selected ${category()}: ${selected()}`) ? div({ class: 'alert alert-success mt-2' }, () => `Selected ${category()}: ${selected()}`)
: null : null
]); ]);
}; };

View File

@@ -46,7 +46,7 @@ Range supports all **daisyUI Range classes**:
const BasicDemo = () => { const BasicDemo = () => {
const value = $(50); const value = $(50);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Range({ Range({
label: 'Volume', label: 'Volume',
value: value, value: value,
@@ -54,7 +54,7 @@ const BasicDemo = () => {
max: 100, max: 100,
oninput: (e) => value(parseInt(e.target.value)) oninput: (e) => value(parseInt(e.target.value))
}), }),
Div({ class: 'text-center' }, () => `Value: ${value()}%`) div({ class: 'text-center' }, () => `Value: ${value()}%`)
]); ]);
}; };
mount(BasicDemo, '#demo-basic'); mount(BasicDemo, '#demo-basic');
@@ -73,7 +73,7 @@ mount(BasicDemo, '#demo-basic');
const TooltipDemo = () => { const TooltipDemo = () => {
const brightness = $(75); const brightness = $(75);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Range({ Range({
label: 'Brightness', label: 'Brightness',
value: brightness, value: brightness,
@@ -82,7 +82,7 @@ const TooltipDemo = () => {
tooltip: () => `${brightness()}% brightness`, tooltip: () => `${brightness()}% brightness`,
oninput: (e) => brightness(parseInt(e.target.value)) oninput: (e) => brightness(parseInt(e.target.value))
}), }),
Div({ class: 'w-full h-20 rounded-lg transition-all', style: () => `background-color: hsl(0, 0%, ${brightness()}%)` }) div({ class: 'w-full h-20 rounded-lg transition-all', style: () => `background-color: hsl(0, 0%, ${brightness()}%)` })
]); ]);
}; };
mount(TooltipDemo, '#demo-tooltip'); mount(TooltipDemo, '#demo-tooltip');
@@ -103,7 +103,7 @@ const ColorsDemo = () => {
const secondary = $(60); const secondary = $(60);
const accent = $(90); const accent = $(90);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Range({ label: 'Primary', value: primary, class: 'range-primary', oninput: (e) => primary(e.target.value) }), Range({ label: 'Primary', value: primary, class: 'range-primary', oninput: (e) => primary(e.target.value) }),
Range({ label: 'Secondary', value: secondary, class: 'range-secondary', oninput: (e) => secondary(e.target.value) }), Range({ label: 'Secondary', value: secondary, class: 'range-secondary', oninput: (e) => secondary(e.target.value) }),
Range({ label: 'Accent', value: accent, class: 'range-accent', oninput: (e) => accent(e.target.value) }) Range({ label: 'Accent', value: accent, class: 'range-accent', oninput: (e) => accent(e.target.value) })
@@ -128,7 +128,7 @@ const SizesDemo = () => {
const md = $(75); const md = $(75);
const lg = $(100); const lg = $(100);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Range({ label: 'Extra Small', value: xs, class: 'range-xs', oninput: (e) => xs(e.target.value) }), Range({ label: 'Extra Small', value: xs, class: 'range-xs', oninput: (e) => xs(e.target.value) }),
Range({ label: 'Small', value: sm, class: 'range-sm', oninput: (e) => sm(e.target.value) }), Range({ label: 'Small', value: sm, class: 'range-sm', oninput: (e) => sm(e.target.value) }),
Range({ label: 'Medium', value: md, class: 'range-md', oninput: (e) => md(e.target.value) }), Range({ label: 'Medium', value: md, class: 'range-md', oninput: (e) => md(e.target.value) }),
@@ -152,7 +152,7 @@ const PriceDemo = () => {
const price = $(500); const price = $(500);
const maxPrice = 1000; const maxPrice = 1000;
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Range({ Range({
label: 'Price Range', label: 'Price Range',
value: price, value: price,
@@ -161,12 +161,12 @@ const PriceDemo = () => {
step: 10, step: 10,
oninput: (e) => price(parseInt(e.target.value)) oninput: (e) => price(parseInt(e.target.value))
}), }),
Div({ class: 'flex justify-between' }, [ div({ class: 'flex justify-between' }, [
Span({}, '$0'), span({}, '$0'),
Span({}, () => `$${price()}`), span({}, () => `$${price()}`),
Span({}, `$${maxPrice}`) span({}, `$${maxPrice}`)
]), ]),
Div({ class: 'mt-2 text-sm opacity-70' }, () => { div({ class: 'mt-2 text-sm opacity-70' }, () => {
if (price() < 250) return 'Budget friendly'; if (price() < 250) return 'Budget friendly';
if (price() < 750) return 'Mid range'; if (price() < 750) return 'Mid range';
return 'Premium'; return 'Premium';
@@ -191,9 +191,9 @@ const AudioDemo = () => {
const bass = $(40); const bass = $(40);
const treble = $(60); const treble = $(60);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex items-center gap-3' }, [ div({ class: 'flex items-center gap-3' }, [
Span({ class: 'w-12' }, '🔊'), span({ class: 'w-12' }, '🔊'),
Range({ Range({
value: volume, value: volume,
min: 0, min: 0,
@@ -201,10 +201,10 @@ const AudioDemo = () => {
class: 'range-primary flex-1', class: 'range-primary flex-1',
oninput: (e) => volume(e.target.value) oninput: (e) => volume(e.target.value)
}), }),
Span({ class: 'w-12 text-right' }, () => `${volume()}%`) span({ class: 'w-12 text-right' }, () => `${volume()}%`)
]), ]),
Div({ class: 'flex items-center gap-3' }, [ div({ class: 'flex items-center gap-3' }, [
Span({ class: 'w-12' }, '🎵 Bass'), span({ class: 'w-12' }, '🎵 Bass'),
Range({ Range({
value: bass, value: bass,
min: 0, min: 0,
@@ -212,10 +212,10 @@ const AudioDemo = () => {
class: 'range-secondary flex-1', class: 'range-secondary flex-1',
oninput: (e) => bass(e.target.value) oninput: (e) => bass(e.target.value)
}), }),
Span({ class: 'w-12 text-right' }, () => `${bass()}%`) span({ class: 'w-12 text-right' }, () => `${bass()}%`)
]), ]),
Div({ class: 'flex items-center gap-3' }, [ div({ class: 'flex items-center gap-3' }, [
Span({ class: 'w-12' }, '🎶 Treble'), span({ class: 'w-12' }, '🎶 Treble'),
Range({ Range({
value: treble, value: treble,
min: 0, min: 0,
@@ -223,7 +223,7 @@ const AudioDemo = () => {
class: 'range-accent flex-1', class: 'range-accent flex-1',
oninput: (e) => treble(e.target.value) oninput: (e) => treble(e.target.value)
}), }),
Span({ class: 'w-12 text-right' }, () => `${treble()}%`) span({ class: 'w-12 text-right' }, () => `${treble()}%`)
]) ])
]); ]);
}; };
@@ -243,14 +243,14 @@ mount(AudioDemo, '#demo-audio');
const VariantsDemo = () => { const VariantsDemo = () => {
const value = $(50); const value = $(50);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-sm font-bold' }, 'With Label'), div({ class: 'text-sm font-bold' }, 'With Label'),
Range({ label: 'Label', value: $(50), oninput: (e) => {} }), Range({ label: 'Label', value: $(50), oninput: (e) => {} }),
Div({ class: 'text-sm font-bold mt-2' }, 'With Tooltip'), div({ class: 'text-sm font-bold mt-2' }, 'With Tooltip'),
Range({ tooltip: 'Tooltip message', value: $(50), oninput: (e) => {} }), Range({ tooltip: 'Tooltip message', value: $(50), oninput: (e) => {} }),
Div({ class: 'text-sm font-bold mt-2' }, 'Disabled'), div({ class: 'text-sm font-bold mt-2' }, 'Disabled'),
Range({ disabled: true, value: $(50), oninput: (e) => {} }) Range({ disabled: true, value: $(50), oninput: (e) => {} })
]); ]);
}; };

View File

@@ -45,13 +45,13 @@ Rating supports all **daisyUI Rating classes**:
const BasicDemo = () => { const BasicDemo = () => {
const rating = $(3); const rating = $(3);
return Div({ class: 'flex flex-col gap-2 items-center' }, [ return div({ class: 'flex flex-col gap-2 items-center' }, [
Rating({ Rating({
value: rating, value: rating,
count: 5, count: 5,
onchange: (value) => rating(value) onchange: (value) => rating(value)
}), }),
Div({ class: 'text-sm opacity-70' }, () => `Rating: ${rating()} / 5`) div({ class: 'text-sm opacity-70' }, () => `Rating: ${rating()} / 5`)
]); ]);
}; };
mount(BasicDemo, '#demo-basic'); mount(BasicDemo, '#demo-basic');
@@ -70,14 +70,14 @@ mount(BasicDemo, '#demo-basic');
const HeartDemo = () => { const HeartDemo = () => {
const rating = $(4); const rating = $(4);
return Div({ class: 'flex flex-col gap-2 items-center' }, [ return div({ class: 'flex flex-col gap-2 items-center' }, [
Rating({ Rating({
value: rating, value: rating,
count: 5, count: 5,
mask: 'mask-heart', mask: 'mask-heart',
onchange: (value) => rating(value) onchange: (value) => rating(value)
}), }),
Div({ class: 'text-sm opacity-70' }, () => `${rating()} hearts`) div({ class: 'text-sm opacity-70' }, () => `${rating()} hearts`)
]); ]);
}; };
mount(HeartDemo, '#demo-heart'); mount(HeartDemo, '#demo-heart');
@@ -96,14 +96,14 @@ mount(HeartDemo, '#demo-heart');
const Star2Demo = () => { const Star2Demo = () => {
const rating = $(2); const rating = $(2);
return Div({ class: 'flex flex-col gap-2 items-center' }, [ return div({ class: 'flex flex-col gap-2 items-center' }, [
Rating({ Rating({
value: rating, value: rating,
count: 5, count: 5,
mask: 'mask-star-2', mask: 'mask-star-2',
onchange: (value) => rating(value) onchange: (value) => rating(value)
}), }),
Div({ class: 'text-sm opacity-70' }, () => `${rating()} stars`) div({ class: 'text-sm opacity-70' }, () => `${rating()} stars`)
]); ]);
}; };
mount(Star2Demo, '#demo-star2'); mount(Star2Demo, '#demo-star2');
@@ -122,13 +122,13 @@ mount(Star2Demo, '#demo-star2');
const ReadonlyDemo = () => { const ReadonlyDemo = () => {
const rating = $(4.5); const rating = $(4.5);
return Div({ class: 'flex flex-col gap-2 items-center' }, [ return div({ class: 'flex flex-col gap-2 items-center' }, [
Rating({ Rating({
value: rating, value: rating,
count: 5, count: 5,
readonly: true readonly: true
}), }),
Div({ class: 'text-sm opacity-70' }, 'Average rating: 4.5/5 (read-only)') div({ class: 'text-sm opacity-70' }, 'Average rating: 4.5/5 (read-only)')
]); ]);
}; };
mount(ReadonlyDemo, '#demo-readonly'); mount(ReadonlyDemo, '#demo-readonly');
@@ -151,27 +151,27 @@ const ReviewDemo = () => {
const average = () => Math.round(((quality() + price() + support()) / 3) * 10) / 10; const average = () => Math.round(((quality() + price() + support()) / 3) * 10) / 10;
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-lg font-bold' }, 'Product Review'), div({ class: 'text-lg font-bold' }, 'Product Review'),
Div({ class: 'flex flex-col gap-2' }, [ div({ class: 'flex flex-col gap-2' }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({ class: 'text-sm w-24' }, 'Quality:'), span({ class: 'text-sm w-24' }, 'Quality:'),
Rating({ Rating({
value: quality, value: quality,
count: 5, count: 5,
onchange: (v) => quality(v) onchange: (v) => quality(v)
}) })
]), ]),
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({ class: 'text-sm w-24' }, 'Price:'), span({ class: 'text-sm w-24' }, 'Price:'),
Rating({ Rating({
value: price, value: price,
count: 5, count: 5,
onchange: (v) => price(v) onchange: (v) => price(v)
}) })
]), ]),
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({ class: 'text-sm w-24' }, 'Support:'), span({ class: 'text-sm w-24' }, 'Support:'),
Rating({ Rating({
value: support, value: support,
count: 5, count: 5,
@@ -179,10 +179,10 @@ const ReviewDemo = () => {
}) })
]) ])
]), ]),
Div({ class: 'divider my-1' }), div({ class: 'divider my-1' }),
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({ class: 'font-bold' }, 'Overall:'), span({ class: 'font-bold' }, 'Overall:'),
Div({ class: 'text-2xl font-bold text-primary' }, () => average()) div({ class: 'text-2xl font-bold text-primary' }, () => average())
]) ])
]); ]);
}; };
@@ -200,21 +200,21 @@ mount(ReviewDemo, '#demo-review');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'flex flex-col gap-6' }, [ return div({ class: 'flex flex-col gap-6' }, [
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-sm mb-2' }, 'Mask Star'), div({ class: 'text-sm mb-2' }, 'Mask Star'),
Rating({ value: $(3), count: 5, mask: 'mask-star' }) Rating({ value: $(3), count: 5, mask: 'mask-star' })
]), ]),
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-sm mb-2' }, 'Mask Star 2 (yellow)'), div({ class: 'text-sm mb-2' }, 'Mask Star 2 (yellow)'),
Rating({ value: $(4), count: 5, mask: 'mask-star-2', class: 'rating-warning' }) Rating({ value: $(4), count: 5, mask: 'mask-star-2', class: 'rating-warning' })
]), ]),
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-sm mb-2' }, 'Mask Heart'), div({ class: 'text-sm mb-2' }, 'Mask Heart'),
Rating({ value: $(5), count: 5, mask: 'mask-heart', class: 'rating-error' }) Rating({ value: $(5), count: 5, mask: 'mask-heart', class: 'rating-error' })
]), ]),
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-sm mb-2' }, 'Half Stars (read-only)'), div({ class: 'text-sm mb-2' }, 'Half Stars (read-only)'),
Rating({ value: $(3.5), count: 5, readonly: true }) Rating({ value: $(3.5), count: 5, readonly: true })
]) ])
]); ]);
@@ -243,9 +243,9 @@ const FeedbackDemo = () => {
5: 'Excellent! 🎉' 5: 'Excellent! 🎉'
}; };
return Div({ class: 'flex flex-col gap-4 items-center' }, [ return div({ class: 'flex flex-col gap-4 items-center' }, [
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-sm mb-2' }, 'How was your experience?'), div({ class: 'text-sm mb-2' }, 'How was your experience?'),
Rating({ Rating({
value: rating, value: rating,
count: 5, count: 5,
@@ -262,7 +262,7 @@ const FeedbackDemo = () => {
}) })
]), ]),
() => rating() > 0 () => rating() > 0
? Div({ class: 'alert alert-soft text-center' }, [ ? div({ class: 'alert alert-soft text-center' }, [
messages[rating()] || `Rating: ${rating()} stars` messages[rating()] || `Rating: ${rating()} stars`
]) ])
: null : null

View File

@@ -49,9 +49,9 @@ Select supports all **daisyUI Select classes**:
const BasicDemo = () => { const BasicDemo = () => {
const selected = $('apple'); const selected = $('apple');
return Div({ class: 'form-control w-full max-w-xs' }, [ return div({ class: 'form-control w-full max-w-xs' }, [
Label({ class: 'label' }, Span({ class: 'label-text' }, 'Choose a fruit')), label({ class: 'label' }, span({ class: 'label-text' }, 'Choose a fruit')),
Select({ select({
class: 'select select-bordered w-full', class: 'select select-bordered w-full',
value: selected, value: selected,
onchange: (e) => selected(e.target.value) onchange: (e) => selected(e.target.value)
@@ -82,10 +82,10 @@ mount(BasicDemo, '#demo-basic');
```javascript ```javascript
const ReactiveDemo = () => { const ReactiveDemo = () => {
const selected = $('small'); const selected = $('small');
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Div({ class: 'form-control w-full max-w-xs' }, [ div({ class: 'form-control w-full max-w-xs' }, [
Label({ class: 'label' }, Span({ class: 'label-text' }, 'Select size')), label({ class: 'label' }, span({ class: 'label-text' }, 'Select size')),
Select({ select({
class: 'select select-bordered w-full', class: 'select select-bordered w-full',
value: selected, value: selected,
onchange: (e) => selected(e.target.value) onchange: (e) => selected(e.target.value)
@@ -99,7 +99,7 @@ const ReactiveDemo = () => {
}) })
]) ])
]), ]),
Div({ class: 'alert alert-info' }, () => `You selected: ${selected()}`) div({ class: 'alert alert-info' }, () => `You selected: ${selected()}`)
]); ]);
}; };
mount(ReactiveDemo, '#demo-reactive'); mount(ReactiveDemo, '#demo-reactive');
@@ -116,9 +116,9 @@ mount(ReactiveDemo, '#demo-reactive');
```javascript ```javascript
const DisabledDemo = () => { const DisabledDemo = () => {
return Div({ class: 'form-control w-full max-w-xs' }, [ return div({ class: 'form-control w-full max-w-xs' }, [
Label({ class: 'label' }, Span({ class: 'label-text' }, 'Country (disabled)')), label({ class: 'label' }, span({ class: 'label-text' }, 'Country (disabled)')),
Select({ select({
class: 'select select-bordered w-full', class: 'select select-bordered w-full',
value: 'mx', value: 'mx',
disabled: true disabled: true
@@ -161,10 +161,10 @@ const DynamicDemo = () => {
] ]
}; };
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Div({ class: 'form-control w-full max-w-xs' }, [ div({ class: 'form-control w-full max-w-xs' }, [
Label({ class: 'label' }, Span({ class: 'label-text' }, 'Category')), label({ class: 'label' }, span({ class: 'label-text' }, 'Category')),
Select({ select({
class: 'select select-bordered w-full', class: 'select select-bordered w-full',
value: category, value: category,
onchange: (e) => { onchange: (e) => {
@@ -180,9 +180,9 @@ const DynamicDemo = () => {
}) })
]) ])
]), ]),
Div({ class: 'form-control w-full max-w-xs' }, [ div({ class: 'form-control w-full max-w-xs' }, [
Label({ class: 'label' }, Span({ class: 'label-text' }, 'Item')), label({ class: 'label' }, span({ class: 'label-text' }, 'Item')),
Select({ select({
class: 'select select-bordered w-full', class: 'select select-bordered w-full',
value: selectedItem, value: selectedItem,
onchange: (e) => selectedItem(e.target.value) onchange: (e) => selectedItem(e.target.value)
@@ -192,7 +192,7 @@ const DynamicDemo = () => {
}) })
]) ])
]), ]),
() => selectedItem() ? Div({ class: 'alert alert-success' }, `Selected: ${selectedItem()}`) : null () => selectedItem() ? div({ class: 'alert alert-success' }, `Selected: ${selectedItem()}`) : null
]); ]);
}; };
mount(DynamicDemo, '#demo-dynamic'); mount(DynamicDemo, '#demo-dynamic');
@@ -213,10 +213,10 @@ const VariantsDemo = () => {
const secondary = $('option2'); const secondary = $('option2');
const ghost = $(''); const ghost = $('');
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'form-control w-full max-w-xs' }, [ div({ class: 'form-control w-full max-w-xs' }, [
Label({ class: 'label' }, Span({ class: 'label-text' }, 'Primary Select')), label({ class: 'label' }, span({ class: 'label-text' }, 'Primary Select')),
Select({ select({
class: 'select select-primary w-full', class: 'select select-primary w-full',
value: primary, value: primary,
onchange: (e) => primary(e.target.value) onchange: (e) => primary(e.target.value)
@@ -230,9 +230,9 @@ const VariantsDemo = () => {
}) })
]) ])
]), ]),
Div({ class: 'form-control w-full max-w-xs' }, [ div({ class: 'form-control w-full max-w-xs' }, [
Label({ class: 'label' }, Span({ class: 'label-text' }, 'Secondary Select')), label({ class: 'label' }, span({ class: 'label-text' }, 'Secondary Select')),
Select({ select({
class: 'select select-secondary w-full', class: 'select select-secondary w-full',
value: secondary, value: secondary,
onchange: (e) => secondary(e.target.value) onchange: (e) => secondary(e.target.value)
@@ -245,9 +245,9 @@ const VariantsDemo = () => {
}) })
]) ])
]), ]),
Div({ class: 'form-control w-full max-w-xs' }, [ div({ class: 'form-control w-full max-w-xs' }, [
Label({ class: 'label' }, Span({ class: 'label-text' }, 'Ghost Select')), label({ class: 'label' }, span({ class: 'label-text' }, 'Ghost Select')),
Select({ select({
class: 'select select-ghost w-full', class: 'select select-ghost w-full',
value: ghost, value: ghost,
onchange: (e) => ghost(e.target.value) onchange: (e) => ghost(e.target.value)

View File

@@ -39,9 +39,9 @@ Stack supports all **daisyUI Stack classes**:
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Stack({ class: 'w-40' }, [ return Stack({ class: 'w-40' }, [
Div({ class: 'bg-primary text-primary-content rounded-lg p-4 shadow-lg' }, 'Layer 1'), div({ class: 'bg-primary text-primary-content rounded-lg p-4 shadow-lg' }, 'Layer 1'),
Div({ class: 'bg-secondary text-secondary-content rounded-lg p-4 shadow-lg' }, 'Layer 2'), div({ class: 'bg-secondary text-secondary-content rounded-lg p-4 shadow-lg' }, 'Layer 2'),
Div({ class: 'bg-accent text-accent-content rounded-lg p-4 shadow-lg' }, 'Layer 3') div({ class: 'bg-accent text-accent-content rounded-lg p-4 shadow-lg' }, 'Layer 3')
]); ]);
}; };
mount(BasicDemo, '#demo-basic'); mount(BasicDemo, '#demo-basic');
@@ -59,16 +59,16 @@ mount(BasicDemo, '#demo-basic');
```javascript ```javascript
const CardsDemo = () => { const CardsDemo = () => {
return Stack({ class: 'w-64' }, [ return Stack({ class: 'w-64' }, [
Div({ class: 'card bg-base-100 shadow-xl border border-base-300' }, [ div({ class: 'card bg-base-100 shadow-xl border border-base-300' }, [
Div({ class: 'card-body p-4' }, [ div({ class: 'card-body p-4' }, [
Span({ class: 'text-sm opacity-70' }, 'Back Card'), span({ class: 'text-sm opacity-70' }, 'Back Card'),
Span({ class: 'font-bold' }, 'Additional info') span({ class: 'font-bold' }, 'Additional info')
]) ])
]), ]),
Div({ class: 'card bg-primary text-primary-content shadow-xl' }, [ div({ class: 'card bg-primary text-primary-content shadow-xl' }, [
Div({ class: 'card-body p-4' }, [ div({ class: 'card-body p-4' }, [
Span({ class: 'text-sm' }, 'Front Card'), span({ class: 'text-sm' }, 'Front Card'),
Span({ class: 'font-bold text-lg' }, 'Main Content') span({ class: 'font-bold text-lg' }, 'Main Content')
]) ])
]) ])
]); ]);
@@ -88,14 +88,14 @@ mount(CardsDemo, '#demo-cards');
```javascript ```javascript
const AvatarsDemo = () => { const AvatarsDemo = () => {
return Stack({ class: 'w-32' }, [ return Stack({ class: 'w-32' }, [
Div({ class: 'avatar placeholder' }, [ div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-neutral text-neutral-content rounded-full w-16 h-16 flex items-center justify-center' }, 'JD') div({ class: 'bg-neutral text-neutral-content rounded-full w-16 h-16 flex items-center justify-center' }, 'JD')
]), ]),
Div({ class: 'avatar placeholder' }, [ div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-primary text-primary-content rounded-full w-16 h-16 flex items-center justify-center' }, 'JS') div({ class: 'bg-primary text-primary-content rounded-full w-16 h-16 flex items-center justify-center' }, 'JS')
]), ]),
Div({ class: 'avatar placeholder' }, [ div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-secondary text-secondary-content rounded-full w-16 h-16 flex items-center justify-center' }, 'BC') div({ class: 'bg-secondary text-secondary-content rounded-full w-16 h-16 flex items-center justify-center' }, 'BC')
]) ])
]); ]);
}; };
@@ -114,14 +114,14 @@ mount(AvatarsDemo, '#demo-avatars');
```javascript ```javascript
const ImagesDemo = () => { const ImagesDemo = () => {
return Stack({ class: 'w-48' }, [ return Stack({ class: 'w-48' }, [
Div({ class: 'w-full h-32 bg-gradient-to-r from-primary to-secondary rounded-lg shadow-lg' }, [ div({ class: 'w-full h-32 bg-gradient-to-r from-primary to-secondary rounded-lg shadow-lg' }, [
Div({ class: 'p-2 text-white text-sm' }, 'Background Image') div({ class: 'p-2 text-white text-sm' }, 'Background Image')
]), ]),
Div({ class: 'w-full h-32 bg-gradient-to-r from-secondary to-accent rounded-lg shadow-lg translate-x-2 translate-y-2' }, [ div({ class: 'w-full h-32 bg-gradient-to-r from-secondary to-accent rounded-lg shadow-lg translate-x-2 translate-y-2' }, [
Div({ class: 'p-2 text-white text-sm' }, 'Middle Layer') div({ class: 'p-2 text-white text-sm' }, 'Middle Layer')
]), ]),
Div({ class: 'w-full h-32 bg-gradient-to-r from-accent to-primary rounded-lg shadow-lg translate-x-4 translate-y-4 flex items-center justify-center' }, [ div({ class: 'w-full h-32 bg-gradient-to-r from-accent to-primary rounded-lg shadow-lg translate-x-4 translate-y-4 flex items-center justify-center' }, [
Span({ class: 'text-white font-bold' }, 'Top Layer') span({ class: 'text-white font-bold' }, 'Top Layer')
]) ])
]); ]);
}; };
@@ -148,11 +148,11 @@ const GalleryDemo = () => {
return Stack({ class: 'w-48 cursor-pointer hover:scale-105 transition-transform' }, [ return Stack({ class: 'w-48 cursor-pointer hover:scale-105 transition-transform' }, [
...photos.map((photo, idx) => ...photos.map((photo, idx) =>
Div({ div({
class: `${photo.color} rounded-lg shadow-lg transition-all`, class: `${photo.color} rounded-lg shadow-lg transition-all`,
style: `transform: translate(${idx * 4}px, ${idx * 4}px);` style: `transform: translate(${idx * 4}px, ${idx * 4}px);`
}, [ }, [
Div({ class: 'p-4 text-white font-bold' }, photo.label) div({ class: 'p-4 text-white font-bold' }, photo.label)
]) ])
) )
]); ]);
@@ -175,21 +175,21 @@ const InteractiveDemo = () => {
const colors = ['primary', 'secondary', 'accent', 'info', 'success']; const colors = ['primary', 'secondary', 'accent', 'info', 'success'];
const labels = ['Home', 'Profile', 'Settings', 'Messages', 'Notifications']; const labels = ['Home', 'Profile', 'Settings', 'Messages', 'Notifications'];
return Div({ class: 'flex flex-col gap-6 items-center' }, [ return div({ class: 'flex flex-col gap-6 items-center' }, [
Stack({ class: 'w-56' }, colors.map((color, idx) => Stack({ class: 'w-56' }, colors.map((color, idx) =>
Div({ div({
class: () => `bg-${color} text-${color}-content rounded-lg p-4 shadow-lg transition-all cursor-pointer ${idx === active() ? 'scale-105 z-10' : ''}`, class: () => `bg-${color} text-${color}-content rounded-lg p-4 shadow-lg transition-all cursor-pointer ${idx === active() ? 'scale-105 z-10' : ''}`,
style: () => `transform: translate(${idx * 8}px, ${idx * 8}px);`, style: () => `transform: translate(${idx * 8}px, ${idx * 8}px);`,
onclick: () => active(idx) onclick: () => active(idx)
}, [ }, [
Div({ class: 'font-bold' }, labels[idx]), div({ class: 'font-bold' }, labels[idx]),
Div({ class: 'text-sm opacity-80' }, `Layer ${idx + 1}`) div({ class: 'text-sm opacity-80' }, `Layer ${idx + 1}`)
]) ])
)), )),
Div({ class: 'mt-4 text-center' }, [ div({ class: 'mt-4 text-center' }, [
Span({ class: 'font-bold' }, () => `Active: ${labels[active()]}`), span({ class: 'font-bold' }, () => `Active: ${labels[active()]}`),
Div({ class: 'flex gap-2 mt-2' }, colors.map((_, idx) => div({ class: 'flex gap-2 mt-2' }, colors.map((_, idx) =>
Button({ button({
class: () => `btn btn-xs ${idx === active() ? 'btn-primary' : 'btn-ghost'}`, class: () => `btn btn-xs ${idx === active() ? 'btn-primary' : 'btn-ghost'}`,
onclick: () => active(idx) onclick: () => active(idx)
}, `${idx + 1}`) }, `${idx + 1}`)
@@ -228,22 +228,22 @@ const NotificationsDemo = () => {
error: 'bg-error text-error-content' error: 'bg-error text-error-content'
}; };
return Div({ class: 'flex flex-col gap-4 items-center' }, [ return div({ class: 'flex flex-col gap-4 items-center' }, [
Stack({ class: 'w-80' }, () => notifications().map((notif, idx) => Stack({ class: 'w-80' }, () => notifications().map((notif, idx) =>
Div({ div({
class: () => `${typeClasses[notif.type]} rounded-lg p-3 shadow-lg transition-all cursor-pointer`, class: () => `${typeClasses[notif.type]} rounded-lg p-3 shadow-lg transition-all cursor-pointer`,
style: () => `transform: translate(${idx * 4}px, ${idx * 4}px);`, style: () => `transform: translate(${idx * 4}px, ${idx * 4}px);`,
onclick: () => removeNotification(notif.id) onclick: () => removeNotification(notif.id)
}, [ }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({ class: 'text-sm' }, notif.message), span({ class: 'text-sm' }, notif.message),
Span({ class: 'text-xs opacity-70 cursor-pointer hover:opacity-100' }, '✕') span({ class: 'text-xs opacity-70 cursor-pointer hover:opacity-100' }, '✕')
]) ])
]) ])
)), )),
() => notifications().length === 0 () => notifications().length === 0
? Div({ class: 'alert alert-soft' }, 'No notifications') ? div({ class: 'alert alert-soft' }, 'No notifications')
: Button({ : button({
class: 'btn btn-sm btn-ghost mt-2', class: 'btn btn-sm btn-ghost mt-2',
onclick: () => notifications([]) onclick: () => notifications([])
}, 'Clear All') }, 'Clear All')
@@ -263,29 +263,29 @@ mount(NotificationsDemo, '#demo-notifications');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'flex flex-wrap gap-8 justify-center' }, [ return div({ class: 'flex flex-wrap gap-8 justify-center' }, [
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-sm mb-2' }, 'Small Stack'), div({ class: 'text-sm mb-2' }, 'Small Stack'),
Stack({ class: 'w-24' }, [ Stack({ class: 'w-24' }, [
Div({ class: 'bg-primary rounded p-2 text-xs' }, '1'), div({ class: 'bg-primary rounded p-2 text-xs' }, '1'),
Div({ class: 'bg-secondary rounded p-2 text-xs' }, '2'), div({ class: 'bg-secondary rounded p-2 text-xs' }, '2'),
Div({ class: 'bg-accent rounded p-2 text-xs' }, '3') div({ class: 'bg-accent rounded p-2 text-xs' }, '3')
]) ])
]), ]),
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-sm mb-2' }, 'Medium Stack'), div({ class: 'text-sm mb-2' }, 'Medium Stack'),
Stack({ class: 'w-32' }, [ Stack({ class: 'w-32' }, [
Div({ class: 'bg-primary rounded p-3' }, 'A'), div({ class: 'bg-primary rounded p-3' }, 'A'),
Div({ class: 'bg-secondary rounded p-3' }, 'B'), div({ class: 'bg-secondary rounded p-3' }, 'B'),
Div({ class: 'bg-accent rounded p-3' }, 'C') div({ class: 'bg-accent rounded p-3' }, 'C')
]) ])
]), ]),
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-sm mb-2' }, 'Large Stack'), div({ class: 'text-sm mb-2' }, 'Large Stack'),
Stack({ class: 'w-40' }, [ Stack({ class: 'w-40' }, [
Div({ class: 'bg-primary rounded p-4' }, 'X'), div({ class: 'bg-primary rounded p-4' }, 'X'),
Div({ class: 'bg-secondary rounded p-4' }, 'Y'), div({ class: 'bg-secondary rounded p-4' }, 'Y'),
Div({ class: 'bg-accent rounded p-4' }, 'Z') div({ class: 'bg-accent rounded p-4' }, 'Z')
]) ])
]) ])
]); ]);

View File

@@ -41,7 +41,7 @@ Stat supports all **daisyUI Stat classes**:
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [ return div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [
Stat({ Stat({
label: 'Total Users', label: 'Total Users',
value: '2,345', value: '2,345',
@@ -73,24 +73,24 @@ mount(BasicDemo, '#demo-basic');
```javascript ```javascript
const IconsDemo = () => { const IconsDemo = () => {
return Div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [ return div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [
Stat({ Stat({
label: 'Active Users', label: 'Active Users',
value: '1,234', value: '1,234',
desc: 'Currently online', desc: 'Currently online',
icon: Span({ class: 'text-4xl' }, '👥') // text-4xl para emojis icon: span({ class: 'text-4xl' }, '👥') // text-4xl para emojis
}), }),
Stat({ Stat({
label: 'New Orders', label: 'New Orders',
value: '89', value: '89',
desc: 'Today', desc: 'Today',
icon: Span({ class: 'text-4xl' }, '📦') icon: span({ class: 'text-4xl' }, '📦')
}), }),
Stat({ Stat({
label: 'Pending Tasks', label: 'Pending Tasks',
value: '23', value: '23',
desc: 'Need attention', desc: 'Need attention',
icon: Span({ class: 'text-4xl' }, '⏳') icon: span({ class: 'text-4xl' }, '⏳')
}) })
]); ]);
}; };
@@ -110,27 +110,27 @@ mount(IconsDemo, '#demo-icons');
const ReactiveDemo = () => { const ReactiveDemo = () => {
const count = $(0); const count = $(0);
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, [ div({ class: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, [
Stat({ Stat({
label: 'Counter', label: 'Counter',
value: () => count(), value: () => count(),
desc: 'Click the button to increase', desc: 'Click the button to increase',
icon: Span({ class: 'text-2xl' }, '🔢') icon: span({ class: 'text-2xl' }, '🔢')
}), }),
Stat({ Stat({
label: 'Squared', label: 'Squared',
value: () => Math.pow(count(), 2), value: () => Math.pow(count(), 2),
desc: 'Square of counter', desc: 'Square of counter',
icon: Span({ class: 'text-2xl' }, '📐') icon: span({ class: 'text-2xl' }, '📐')
}) })
]), ]),
Div({ class: 'flex gap-2 justify-center' }, [ div({ class: 'flex gap-2 justify-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => count(count() + 1) onclick: () => count(count() + 1)
}, 'Increment'), }, 'Increment'),
Button({ button({
class: 'btn btn-ghost', class: 'btn btn-ghost',
onclick: () => count(0) onclick: () => count(0)
}, 'Reset') }, 'Reset')
@@ -151,30 +151,30 @@ mount(ReactiveDemo, '#demo-reactive');
```javascript ```javascript
const MultipleDemo = () => { const MultipleDemo = () => {
return Div({ class: 'grid grid-cols-1 md:grid-cols-4 gap-4' }, [ return div({ class: 'grid grid-cols-1 md:grid-cols-4 gap-4' }, [
Stat({ Stat({
label: 'Posts', label: 'Posts',
value: '1,234', value: '1,234',
desc: 'Total content', desc: 'Total content',
icon: Span({ class: 'text-4xl' }, '📝') // text-4xl icon: span({ class: 'text-4xl' }, '📝') // text-4xl
}), }),
Stat({ Stat({
label: 'Comments', label: 'Comments',
value: '8,901', value: '8,901',
desc: 'Engagement', desc: 'Engagement',
icon: Span({ class: 'text-4xl' }, '💬') icon: span({ class: 'text-4xl' }, '💬')
}), }),
Stat({ Stat({
label: 'Likes', label: 'Likes',
value: '12,345', value: '12,345',
desc: 'Reactions', desc: 'Reactions',
icon: Span({ class: 'text-4xl' }, '❤️') icon: span({ class: 'text-4xl' }, '❤️')
}), }),
Stat({ Stat({
label: 'Shares', label: 'Shares',
value: '456', value: '456',
desc: 'Viral reach', desc: 'Viral reach',
icon: Span({ class: 'text-4xl' }, '🔄') icon: span({ class: 'text-4xl' }, '🔄')
}) })
]); ]);
}; };
@@ -208,35 +208,35 @@ const DashboardDemo = () => {
}); });
}; };
return Div({ class: 'flex flex-col gap-6' }, [ return div({ class: 'flex flex-col gap-6' }, [
Div({ class: 'grid grid-cols-1 md:grid-cols-4 gap-4' }, [ div({ class: 'grid grid-cols-1 md:grid-cols-4 gap-4' }, [
Stat({ Stat({
label: 'Total Users', label: 'Total Users',
value: () => stats().users.toLocaleString(), value: () => stats().users.toLocaleString(),
desc: 'Registered users', desc: 'Registered users',
icon: Span({ class: 'text-4xl' }, '👥') // text-4xl icon: span({ class: 'text-4xl' }, '👥') // text-4xl
}), }),
Stat({ Stat({
label: 'Revenue', label: 'Revenue',
value: () => `$${stats().revenue.toLocaleString()}`, value: () => `$${stats().revenue.toLocaleString()}`,
desc: 'This month', desc: 'This month',
icon: Span({ class: 'text-4xl' }, '💰') icon: span({ class: 'text-4xl' }, '💰')
}), }),
Stat({ Stat({
label: 'Orders', label: 'Orders',
value: () => stats().orders.toLocaleString(), value: () => stats().orders.toLocaleString(),
desc: 'Completed', desc: 'Completed',
icon: Span({ class: 'text-4xl' }, '📦') icon: span({ class: 'text-4xl' }, '📦')
}), }),
Stat({ Stat({
label: 'Satisfaction', label: 'Satisfaction',
value: () => `${stats().satisfaction}%`, value: () => `${stats().satisfaction}%`,
desc: stats().satisfaction > 90 ? 'Excellent!' : 'Good', desc: stats().satisfaction > 90 ? 'Excellent!' : 'Good',
icon: Span({ class: 'text-4xl' }, '😊') icon: span({ class: 'text-4xl' }, '😊')
}) })
]), ]),
Div({ class: 'flex justify-center' }, [ div({ class: 'flex justify-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: updateStats onclick: updateStats
}, 'Refresh Data') }, 'Refresh Data')
@@ -257,33 +257,33 @@ mount(DashboardDemo, '#demo-dashboard');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, [ return div({ class: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, [
Stat({ Stat({
label: 'Primary Stat', label: 'Primary Stat',
value: '1,234', value: '1,234',
desc: 'With description', desc: 'With description',
icon: Span({ class: 'text-4xl' }, '⭐'), // text-4xl icon: span({ class: 'text-4xl' }, '⭐'), // text-4xl
class: 'bg-primary/10 text-primary' class: 'bg-primary/10 text-primary'
}), }),
Stat({ Stat({
label: 'Success Stat', label: 'Success Stat',
value: '89%', value: '89%',
desc: 'Success rate', desc: 'Success rate',
icon: Span({ class: 'text-4xl' }, '✅'), icon: span({ class: 'text-4xl' }, '✅'),
class: 'bg-success/10 text-success' class: 'bg-success/10 text-success'
}), }),
Stat({ Stat({
label: 'Warning Stat', label: 'Warning Stat',
value: '23', value: '23',
desc: 'Pending items', desc: 'Pending items',
icon: Span({ class: 'text-4xl' }, '⚠️'), icon: span({ class: 'text-4xl' }, '⚠️'),
class: 'bg-warning/10 text-warning' class: 'bg-warning/10 text-warning'
}), }),
Stat({ Stat({
label: 'Error Stat', label: 'Error Stat',
value: '5', value: '5',
desc: 'Failed attempts', desc: 'Failed attempts',
icon: Span({ class: 'text-4xl' }, '❌'), icon: span({ class: 'text-4xl' }, '❌'),
class: 'bg-error/10 text-error' class: 'bg-error/10 text-error'
}) })
]); ]);
@@ -302,7 +302,7 @@ mount(VariantsDemo, '#demo-variants');
```javascript ```javascript
const CompactDemo = () => { const CompactDemo = () => {
return Div({ class: 'flex flex-wrap gap-4' }, [ return div({ class: 'flex flex-wrap gap-4' }, [
Stat({ Stat({
label: 'Views', label: 'Views',
value: '12.3K', value: '12.3K',

View File

@@ -111,8 +111,8 @@ const CustomDemo = () => {
return Swap({ return Swap({
value: isOn, value: isOn,
on: Div({ class: "badge badge-success gap-1" }, ["✅", " Active"]), on: div({ class: "badge badge-success gap-1" }, ["✅", " Active"]),
off: Div({ class: "badge badge-ghost gap-1" }, ["⭕", " Inactive"]) off: div({ class: "badge badge-ghost gap-1" }, ["⭕", " Inactive"])
}); });
}; };
mount(CustomDemo, '#demo-custom'); mount(CustomDemo, '#demo-custom');
@@ -131,16 +131,16 @@ mount(CustomDemo, '#demo-custom');
const ReactiveDemo = () => { const ReactiveDemo = () => {
const isOn = $(false); const isOn = $(false);
return Div({ class: 'flex flex-col gap-4 items-center' }, [ return div({ class: 'flex flex-col gap-4 items-center' }, [
Swap({ Swap({
value: isOn, value: isOn,
on: "👁️", on: "👁️",
off: "👁️‍🗨️" off: "👁️‍🗨️"
}), }),
Div({ class: 'text-center' }, () => div({ class: 'text-center' }, () =>
isOn() isOn()
? Div({ class: 'alert alert-success' }, 'Content is visible') ? div({ class: 'alert alert-success' }, 'Content is visible')
: Div({ class: 'alert alert-soft' }, 'Content is hidden') : div({ class: 'alert alert-soft' }, 'Content is hidden')
) )
]); ]);
}; };
@@ -162,33 +162,33 @@ const ModeDemo = () => {
const notifications = $(true); const notifications = $(true);
const sound = $(false); const sound = $(false);
return Div({ class: 'flex flex-col gap-4 w-full' }, [ return div({ class: 'flex flex-col gap-4 w-full' }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({}, 'Dark mode'), span({}, 'Dark mode'),
Swap({ Swap({
value: darkMode, value: darkMode,
on: "🌙", on: "🌙",
off: "☀️" off: "☀️"
}) })
]), ]),
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({}, 'Notifications'), span({}, 'Notifications'),
Swap({ Swap({
value: notifications, value: notifications,
on: "🔔", on: "🔔",
off: "🔕" off: "🔕"
}) })
]), ]),
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({}, 'Sound effects'), span({}, 'Sound effects'),
Swap({ Swap({
value: sound, value: sound,
on: "🔊", on: "🔊",
off: "🔇" off: "🔇"
}) })
]), ]),
Div({ class: 'mt-2 p-3 rounded-lg', style: () => darkMode() ? 'background: #1f2937; color: white' : 'background: #f3f4f6' }, [ div({ class: 'mt-2 p-3 rounded-lg', style: () => darkMode() ? 'background: #1f2937; color: white' : 'background: #f3f4f6' }, [
Div({ class: 'text-sm' }, () => `Mode: ${darkMode() ? 'Dark' : 'Light'} | Notifications: ${notifications() ? 'On' : 'Off'} | Sound: ${sound() ? 'On' : 'Off'}`) div({ class: 'text-sm' }, () => `Mode: ${darkMode() ? 'Dark' : 'Light'} | Notifications: ${notifications() ? 'On' : 'Off'} | Sound: ${sound() ? 'On' : 'Off'}`)
]) ])
]); ]);
}; };
@@ -206,33 +206,33 @@ mount(ModeDemo, '#demo-mode');
```javascript ```javascript
const VariantsDemo = () => { const VariantsDemo = () => {
return Div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [ return div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-xs mb-2' }, 'Volume'), div({ class: 'text-xs mb-2' }, 'Volume'),
Swap({ Swap({
value: $(false), value: $(false),
on: "🔊", on: "🔊",
off: "🔇" off: "🔇"
}) })
]), ]),
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-xs mb-2' }, 'Like'), div({ class: 'text-xs mb-2' }, 'Like'),
Swap({ Swap({
value: $(true), value: $(true),
on: "❤️", on: "❤️",
off: "🤍" off: "🤍"
}) })
]), ]),
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-xs mb-2' }, 'Star'), div({ class: 'text-xs mb-2' }, 'Star'),
Swap({ Swap({
value: $(false), value: $(false),
on: "⭐", on: "⭐",
off: "☆" off: "☆"
}) })
]), ]),
Div({ class: 'text-center' }, [ div({ class: 'text-center' }, [
Div({ class: 'text-xs mb-2' }, 'Check'), div({ class: 'text-xs mb-2' }, 'Check'),
Swap({ Swap({
value: $(true), value: $(true),
on: "✅", on: "✅",
@@ -261,11 +261,11 @@ const TodoDemo = () => {
{ id: 3, text: 'Deploy to production', completed: $(false) } { id: 3, text: 'Deploy to production', completed: $(false) }
]; ];
return Div({ class: 'flex flex-col gap-3' }, [ return div({ class: 'flex flex-col gap-3' }, [
Div({ class: 'text-sm font-bold mb-2' }, 'Todo list'), div({ class: 'text-sm font-bold mb-2' }, 'Todo list'),
...todos.map(todo => ...todos.map(todo =>
Div({ class: 'flex items-center justify-between p-2 bg-base-200 rounded-lg' }, [ div({ class: 'flex items-center justify-between p-2 bg-base-200 rounded-lg' }, [
Span({ class: todo.completed() ? 'line-through opacity-50' : '' }, todo.text), span({ class: todo.completed() ? 'line-through opacity-50' : '' }, todo.text),
Swap({ Swap({
value: todo.completed, value: todo.completed,
on: "✅", on: "✅",
@@ -273,7 +273,7 @@ const TodoDemo = () => {
}) })
]) ])
), ),
Div({ class: 'mt-2 text-sm opacity-70' }, () => { div({ class: 'mt-2 text-sm opacity-70' }, () => {
const completed = todos.filter(t => t.completed()).length; const completed = todos.filter(t => t.completed()).length;
return `${completed} of ${todos.length} tasks completed`; return `${completed} of ${todos.length} tasks completed`;
}) })

View File

@@ -60,7 +60,7 @@ const BasicDemo = () => {
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'Editor' } { id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'Editor' }
]; ];
return Table({ return table({
items: users, items: users,
columns: [ columns: [
{ label: 'ID', key: 'id' }, { label: 'ID', key: 'id' },
@@ -91,7 +91,7 @@ const ZebraDemo = () => {
{ id: 4, name: 'Monitor', price: '$299', stock: 12 } { id: 4, name: 'Monitor', price: '$299', stock: 12 }
]; ];
return Table({ return table({
items: products, items: products,
columns: [ columns: [
{ label: 'Product', key: 'name' }, { label: 'Product', key: 'name' },
@@ -121,7 +121,7 @@ const CustomDemo = () => {
{ id: 103, customer: 'Charlie', amount: 450, status: 'shipped' } { id: 103, customer: 'Charlie', amount: 450, status: 'shipped' }
]; ];
return Table({ return table({
items: orders, items: orders,
columns: [ columns: [
{ label: 'Order ID', key: 'id' }, { label: 'Order ID', key: 'id' },
@@ -140,7 +140,7 @@ const CustomDemo = () => {
pending: 'badge badge-warning', pending: 'badge badge-warning',
shipped: 'badge badge-info' shipped: 'badge badge-info'
}; };
return Span({ class: statusClass[item.status] }, item.status); return span({ class: statusClass[item.status] }, item.status);
} }
} }
], ],
@@ -170,7 +170,7 @@ const FooterDemo = () => {
const totalRevenue = sales.reduce((sum, item) => sum + item.revenue, 0); const totalRevenue = sales.reduce((sum, item) => sum + item.revenue, 0);
const totalExpenses = sales.reduce((sum, item) => sum + item.expenses, 0); const totalExpenses = sales.reduce((sum, item) => sum + item.expenses, 0);
return Table({ return table({
items: sales, items: sales,
columns: [ columns: [
{ label: 'Month', key: 'month' }, { label: 'Month', key: 'month' },
@@ -211,15 +211,15 @@ mount(FooterDemo, '#demo-footer');
const EmptyDemo = () => { const EmptyDemo = () => {
const emptyList = []; const emptyList = [];
return Table({ return table({
items: emptyList, items: emptyList,
columns: [ columns: [
{ label: 'ID', key: 'id' }, { label: 'ID', key: 'id' },
{ label: 'Name', key: 'name' } { label: 'Name', key: 'name' }
], ],
empty: Div({ class: 'flex flex-col items-center gap-2 p-4' }, [ empty: div({ class: 'flex flex-col items-center gap-2 p-4' }, [
Span({ class: 'text-2xl' }, '📭'), span({ class: 'text-2xl' }, '📭'),
Span({}, 'No records found') span({}, 'No records found')
]) ])
}); });
}; };
@@ -259,26 +259,26 @@ const ReactiveDemo = () => {
tasks([...tasks(), { id: newId, title: `Task ${newId}`, completed: false }]); tasks([...tasks(), { id: newId, title: `Task ${newId}`, completed: false }]);
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex gap-2' }, [ div({ class: 'flex gap-2' }, [
Button({ button({
class: 'btn btn-sm', class: 'btn btn-sm',
onclick: () => filter('all') onclick: () => filter('all')
}, 'All'), }, 'All'),
Button({ button({
class: 'btn btn-sm', class: 'btn btn-sm',
onclick: () => filter('completed') onclick: () => filter('completed')
}, 'Completed'), }, 'Completed'),
Button({ button({
class: 'btn btn-sm', class: 'btn btn-sm',
onclick: () => filter('pending') onclick: () => filter('pending')
}, 'Pending'), }, 'Pending'),
Button({ button({
class: 'btn btn-sm btn-primary', class: 'btn btn-sm btn-primary',
onclick: addTask onclick: addTask
}, 'Add Task') }, 'Add Task')
]), ]),
Table({ table({
items: filteredTasks, items: filteredTasks,
columns: [ columns: [
{ label: 'ID', key: 'id' }, { label: 'ID', key: 'id' },
@@ -286,8 +286,8 @@ const ReactiveDemo = () => {
{ {
label: 'Status', label: 'Status',
render: (item) => item.completed render: (item) => item.completed
? Span({ class: 'badge badge-success' }, '✓ Done') ? span({ class: 'badge badge-success' }, '✓ Done')
: Span({ class: 'badge badge-warning' }, '○ Pending') : span({ class: 'badge badge-warning' }, '○ Pending')
} }
], ],
zebra: true zebra: true
@@ -325,7 +325,7 @@ const ActionsDemo = () => {
)); ));
}; };
return Table({ return table({
items: users, items: users,
columns: [ columns: [
{ label: 'ID', key: 'id' }, { label: 'ID', key: 'id' },
@@ -334,17 +334,17 @@ const ActionsDemo = () => {
{ {
label: 'Status', label: 'Status',
render: (item) => item.active render: (item) => item.active
? Span({ class: 'badge badge-success' }, 'Active') ? span({ class: 'badge badge-success' }, 'Active')
: Span({ class: 'badge badge-ghost' }, 'Inactive') : span({ class: 'badge badge-ghost' }, 'Inactive')
}, },
{ {
label: 'Actions', label: 'Actions',
render: (item) => Div({ class: 'flex gap-1' }, [ render: (item) => div({ class: 'flex gap-1' }, [
Button({ button({
class: 'btn btn-xs btn-ghost', class: 'btn btn-xs btn-ghost',
onclick: () => toggleActive(item.id) onclick: () => toggleActive(item.id)
}, item.active ? 'Deactivate' : 'Activate'), }, item.active ? 'Deactivate' : 'Activate'),
Button({ button({
class: 'btn btn-xs btn-error', class: 'btn btn-xs btn-error',
onclick: () => deleteUser(item.id) onclick: () => deleteUser(item.id)
}, 'Delete') }, 'Delete')
@@ -374,9 +374,9 @@ const VariantsDemo = () => {
{ id: 3, name: 'Item 3', value: 300 } { id: 3, name: 'Item 3', value: 300 }
]; ];
return Div({ class: 'flex flex-col gap-6' }, [ return div({ class: 'flex flex-col gap-6' }, [
Div({ class: 'text-sm font-bold' }, 'Default Table'), div({ class: 'text-sm font-bold' }, 'Default Table'),
Table({ table({
items: data, items: data,
columns: [ columns: [
{ label: 'ID', key: 'id' }, { label: 'ID', key: 'id' },
@@ -385,8 +385,8 @@ const VariantsDemo = () => {
] ]
}), }),
Div({ class: 'text-sm font-bold mt-4' }, 'Zebra Stripes'), div({ class: 'text-sm font-bold mt-4' }, 'Zebra Stripes'),
Table({ table({
items: data, items: data,
columns: [ columns: [
{ label: 'ID', key: 'id' }, { label: 'ID', key: 'id' },
@@ -396,8 +396,8 @@ const VariantsDemo = () => {
zebra: true zebra: true
}), }),
Div({ class: 'text-sm font-bold mt-4' }, 'Compact Table'), div({ class: 'text-sm font-bold mt-4' }, 'Compact Table'),
Table({ table({
items: data, items: data,
columns: [ columns: [
{ label: 'ID', key: 'id' }, { label: 'ID', key: 'id' },

View File

@@ -70,19 +70,19 @@ const BasicDemo = () => {
label: 'Tab 1', label: 'Tab 1',
active: () => activeTab() === 'tab1', active: () => activeTab() === 'tab1',
onclick: () => activeTab('tab1'), onclick: () => activeTab('tab1'),
content: Div({ class: 'p-4' }, 'Content for Tab 1') content: div({ class: 'p-4' }, 'Content for Tab 1')
}, },
{ {
label: 'Tab 2', label: 'Tab 2',
active: () => activeTab() === 'tab2', active: () => activeTab() === 'tab2',
onclick: () => activeTab('tab2'), onclick: () => activeTab('tab2'),
content: Div({ class: 'p-4' }, 'Content for Tab 2') content: div({ class: 'p-4' }, 'Content for Tab 2')
}, },
{ {
label: 'Tab 3', label: 'Tab 3',
active: () => activeTab() === 'tab3', active: () => activeTab() === 'tab3',
onclick: () => activeTab('tab3'), onclick: () => activeTab('tab3'),
content: Div({ class: 'p-4' }, 'Content for Tab 3') content: div({ class: 'p-4' }, 'Content for Tab 3')
} }
] ]
}); });
@@ -106,22 +106,22 @@ const IconsDemo = () => {
return Tabs({ return Tabs({
items: [ items: [
{ {
label: Span({ class: 'flex items-center gap-2' }, ['🏠', 'Home']), label: span({ class: 'flex items-center gap-2' }, ['🏠', 'Home']),
active: () => activeTab() === 'home', active: () => activeTab() === 'home',
onclick: () => activeTab('home'), onclick: () => activeTab('home'),
content: Div({ class: 'p-4' }, 'Welcome to the Home tab!') content: div({ class: 'p-4' }, 'Welcome to the Home tab!')
}, },
{ {
label: Span({ class: 'flex items-center gap-2' }, ['⭐', 'Favorites']), label: span({ class: 'flex items-center gap-2' }, ['⭐', 'Favorites']),
active: () => activeTab() === 'favorites', active: () => activeTab() === 'favorites',
onclick: () => activeTab('favorites'), onclick: () => activeTab('favorites'),
content: Div({ class: 'p-4' }, 'Your favorite items appear here.') content: div({ class: 'p-4' }, 'Your favorite items appear here.')
}, },
{ {
label: Span({ class: 'flex items-center gap-2' }, ['⚙️', 'Settings']), label: span({ class: 'flex items-center gap-2' }, ['⚙️', 'Settings']),
active: () => activeTab() === 'settings', active: () => activeTab() === 'settings',
onclick: () => activeTab('settings'), onclick: () => activeTab('settings'),
content: Div({ class: 'p-4' }, 'Configure your preferences.') content: div({ class: 'p-4' }, 'Configure your preferences.')
} }
] ]
}); });
@@ -149,21 +149,21 @@ const TooltipsDemo = () => {
tip: 'View your profile information', tip: 'View your profile information',
active: () => activeTab() === 'profile', active: () => activeTab() === 'profile',
onclick: () => activeTab('profile'), onclick: () => activeTab('profile'),
content: Div({ class: 'p-4' }, 'Profile information here.') content: div({ class: 'p-4' }, 'Profile information here.')
}, },
{ {
label: 'Settings', label: 'Settings',
tip: 'Adjust your preferences', tip: 'Adjust your preferences',
active: () => activeTab() === 'settings', active: () => activeTab() === 'settings',
onclick: () => activeTab('settings'), onclick: () => activeTab('settings'),
content: Div({ class: 'p-4' }, 'Settings configuration.') content: div({ class: 'p-4' }, 'Settings configuration.')
}, },
{ {
label: 'Notifications', label: 'Notifications',
tip: 'Manage notifications', tip: 'Manage notifications',
active: () => activeTab() === 'notifications', active: () => activeTab() === 'notifications',
onclick: () => activeTab('notifications'), onclick: () => activeTab('notifications'),
content: Div({ class: 'p-4' }, 'Notification settings.') content: div({ class: 'p-4' }, 'Notification settings.')
} }
] ]
}); });
@@ -190,19 +190,19 @@ const DisabledDemo = () => {
label: 'Basic', label: 'Basic',
active: () => activeTab() === 'basic', active: () => activeTab() === 'basic',
onclick: () => activeTab('basic'), onclick: () => activeTab('basic'),
content: Div({ class: 'p-4' }, 'Basic features available.') content: div({ class: 'p-4' }, 'Basic features available.')
}, },
{ {
label: 'Premium', label: 'Premium',
disabled: true, disabled: true,
tip: 'Upgrade to access', tip: 'Upgrade to access',
content: Div({ class: 'p-4' }, 'Premium content (locked)') content: div({ class: 'p-4' }, 'Premium content (locked)')
}, },
{ {
label: 'Pro', label: 'Pro',
disabled: true, disabled: true,
tip: 'Coming soon', tip: 'Coming soon',
content: Div({ class: 'p-4' }, 'Pro features (coming soon)') content: div({ class: 'p-4' }, 'Pro features (coming soon)')
} }
] ]
}); });
@@ -230,9 +230,9 @@ const ReactiveDemo = () => {
label: 'Counter', label: 'Counter',
active: () => activeTab() === 'counter', active: () => activeTab() === 'counter',
onclick: () => activeTab('counter'), onclick: () => activeTab('counter'),
content: Div({ class: 'p-4 text-center' }, [ content: div({ class: 'p-4 text-center' }, [
Div({ class: 'text-4xl font-bold mb-4' }, () => count()), div({ class: 'text-4xl font-bold mb-4' }, () => count()),
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: () => count(count() + 1) onclick: () => count(count() + 1)
}, 'Increment') }, 'Increment')
@@ -242,13 +242,13 @@ const ReactiveDemo = () => {
label: 'Timer', label: 'Timer',
active: () => activeTab() === 'timer', active: () => activeTab() === 'timer',
onclick: () => activeTab('timer'), onclick: () => activeTab('timer'),
content: Div({ class: 'p-4' }, () => `Current time: ${new Date().toLocaleTimeString()}`) content: div({ class: 'p-4' }, () => `Current time: ${new Date().toLocaleTimeString()}`)
}, },
{ {
label: 'Status', label: 'Status',
active: () => activeTab() === 'status', active: () => activeTab() === 'status',
onclick: () => activeTab('status'), onclick: () => activeTab('status'),
content: Div({ class: 'p-4' }, () => `Counter value: ${count()}, Last updated: ${new Date().toLocaleTimeString()}`) content: div({ class: 'p-4' }, () => `Counter value: ${count()}, Last updated: ${new Date().toLocaleTimeString()}`)
} }
] ]
}); });
@@ -286,21 +286,21 @@ const FormTabs = () => {
console.log(formData()); console.log(formData());
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Tabs({ Tabs({
items: [ items: [
{ {
label: 'Personal Info', label: 'Personal Info',
active: () => activeTab() === 'personal', active: () => activeTab() === 'personal',
onclick: () => activeTab('personal'), onclick: () => activeTab('personal'),
content: Div({ class: 'p-4 space-y-4' }, [ content: div({ class: 'p-4 space-y-4' }, [
Input({ input({
label: 'Name', label: 'Name',
value: () => formData().name, value: () => formData().name,
placeholder: 'Enter your name', placeholder: 'Enter your name',
oninput: (e) => updateField('name', e.target.value) oninput: (e) => updateField('name', e.target.value)
}), }),
Input({ input({
label: 'Email', label: 'Email',
type: 'email', type: 'email',
value: () => formData().email, value: () => formData().email,
@@ -313,14 +313,14 @@ const FormTabs = () => {
label: 'Address', label: 'Address',
active: () => activeTab() === 'address', active: () => activeTab() === 'address',
onclick: () => activeTab('address'), onclick: () => activeTab('address'),
content: Div({ class: 'p-4 space-y-4' }, [ content: div({ class: 'p-4 space-y-4' }, [
Input({ input({
label: 'Address', label: 'Address',
value: () => formData().address, value: () => formData().address,
placeholder: 'Street address', placeholder: 'Street address',
oninput: (e) => updateField('address', e.target.value) oninput: (e) => updateField('address', e.target.value)
}), }),
Input({ input({
label: 'City', label: 'City',
value: () => formData().city, value: () => formData().city,
placeholder: 'City', placeholder: 'City',
@@ -332,7 +332,7 @@ const FormTabs = () => {
label: 'Preferences', label: 'Preferences',
active: () => activeTab() === 'prefs', active: () => activeTab() === 'prefs',
onclick: () => activeTab('prefs'), onclick: () => activeTab('prefs'),
content: Div({ class: 'p-4 space-y-4' }, [ content: div({ class: 'p-4 space-y-4' }, [
Checkbox({ Checkbox({
label: 'Email notifications', label: 'Email notifications',
value: () => formData().notifications, value: () => formData().notifications,
@@ -347,8 +347,8 @@ const FormTabs = () => {
} }
] ]
}), }),
Div({ class: 'flex justify-end mt-4' }, [ div({ class: 'flex justify-end mt-4' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: handleSubmit onclick: handleSubmit
}, 'Submit') }, 'Submit')
@@ -379,39 +379,39 @@ const VariantsDemo = () => {
label: 'Tab 1', label: 'Tab 1',
active: () => active() === 'tab1', active: () => active() === 'tab1',
onclick: () => active('tab1'), onclick: () => active('tab1'),
content: Div({ class: 'p-4' }, 'Content 1') content: div({ class: 'p-4' }, 'Content 1')
}, },
{ {
label: 'Tab 2', label: 'Tab 2',
active: () => active() === 'tab2', active: () => active() === 'tab2',
onclick: () => active('tab2'), onclick: () => active('tab2'),
content: Div({ class: 'p-4' }, 'Content 2') content: div({ class: 'p-4' }, 'Content 2')
}, },
{ {
label: 'Tab 3', label: 'Tab 3',
active: () => active() === 'tab3', active: () => active() === 'tab3',
onclick: () => active('tab3'), onclick: () => active('tab3'),
content: Div({ class: 'p-4' }, 'Content 3') content: div({ class: 'p-4' }, 'Content 3')
}, },
{ {
label: 'Tab 4', label: 'Tab 4',
active: () => active() === 'tab4', active: () => active() === 'tab4',
onclick: () => active('tab4'), onclick: () => active('tab4'),
content: Div({ class: 'p-4' }, 'Content 4') content: div({ class: 'p-4' }, 'Content 4')
} }
]; ];
return Div({ class: 'flex flex-col gap-6' }, [ return div({ class: 'flex flex-col gap-6' }, [
Div({ class: 'text-sm font-bold' }, 'Default Tabs'), div({ class: 'text-sm font-bold' }, 'Default Tabs'),
Tabs({ items: createItems(active1) }), Tabs({ items: createItems(active1) }),
Div({ class: 'text-sm font-bold mt-4' }, 'Boxed Tabs'), div({ class: 'text-sm font-bold mt-4' }, 'Boxed Tabs'),
Tabs({ items: createItems(active2), class: 'tabs-box' }), Tabs({ items: createItems(active2), class: 'tabs-box' }),
Div({ class: 'text-sm font-bold mt-4' }, 'Lifted Tabs'), div({ class: 'text-sm font-bold mt-4' }, 'Lifted Tabs'),
Tabs({ items: createItems(active3), class: 'tabs-lift' }), Tabs({ items: createItems(active3), class: 'tabs-lift' }),
Div({ class: 'text-sm font-bold mt-4' }, 'Bordered Tabs'), div({ class: 'text-sm font-bold mt-4' }, 'Bordered Tabs'),
Tabs({ items: createItems(active4), class: 'tabs-border' }) Tabs({ items: createItems(active4), class: 'tabs-border' })
]); ]);
}; };
@@ -427,9 +427,9 @@ let nextTabId = 4;
const ClosableTabsDemo = () => { const ClosableTabsDemo = () => {
const tabs = $([ const tabs = $([
{ label: 'Tab 1', tip:"Tab1" , content: Div('Content 1') }, // ❌ quita active: true { label: 'Tab 1', tip:"Tab1" , content: div('Content 1') }, // ❌ quita active: true
{ label: 'Tab 2', tip: "Tab 2 Default", content: Div('Content 2'), closable: true }, { label: 'Tab 2', tip: "Tab 2 Default", content: div('Content 2'), closable: true },
{ label: 'Tab 3', content: Div('Content 3'), closable: true } { label: 'Tab 3', content: div('Content 3'), closable: true }
]); ]);
// Opcional: si quieres que la primera pestaña esté activa al inicio, // Opcional: si quieres que la primera pestaña esté activa al inicio,
@@ -440,14 +440,14 @@ const ClosableTabsDemo = () => {
const newId = nextTabId++; const newId = nextTabId++;
tabs([...tabs(), { tabs([...tabs(), {
label: `Tab ${newId}`, label: `Tab ${newId}`,
content: Div(`Content ${newId}`), content: div(`Content ${newId}`),
onClose: (item) => console.log('Closing Individual', item), onClose: (item) => console.log('Closing Individual', item),
closable: true closable: true
}]); }]);
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Button({ class: 'btn btn-sm btn-outline mb-2', onclick: addTab }, 'Add Tab'), button({ class: 'btn btn-sm btn-outline mb-2', onclick: addTab }, 'Add Tab'),
Tabs({ items: tabs, onTabClose: (item) => console.log('Closing', item) }) Tabs({ items: tabs, onTabClose: (item) => console.log('Closing', item) })
]); ]);
}; };

View File

@@ -176,15 +176,15 @@ const ReactiveDemo = () => {
Toast('Order tracking reset', 'alert-warning', 1500); Toast('Order tracking reset', 'alert-warning', 1500);
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Timeline({ items: items }), Timeline({ items: items }),
Div({ class: 'flex gap-2 justify-center mt-4' }, [ div({ class: 'flex gap-2 justify-center mt-4' }, [
Button({ button({
class: 'btn btn-primary btn-sm', class: 'btn btn-primary btn-sm',
onclick: nextStep, onclick: nextStep,
disabled: () => currentStep() >= steps.length disabled: () => currentStep() >= steps.length
}, 'Next Step'), }, 'Next Step'),
Button({ button({
class: 'btn btn-ghost btn-sm', class: 'btn btn-ghost btn-sm',
onclick: reset, onclick: reset,
disabled: () => currentStep() === 0 disabled: () => currentStep() === 0
@@ -224,10 +224,10 @@ const OrderDemo = () => {
completed: idx < currentIndex() completed: idx < currentIndex()
})); }));
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Timeline({ items, compact: true }), Timeline({ items, compact: true }),
Div({ class: 'flex gap-2 justify-center flex-wrap mt-4' }, statusOrder.map(s => div({ class: 'flex gap-2 justify-center flex-wrap mt-4' }, statusOrder.map(s =>
Button({ button({
class: () => `btn btn-xs ${status() === s ? 'btn-primary' : 'btn-ghost'}`, class: () => `btn btn-xs ${status() === s ? 'btn-primary' : 'btn-ghost'}`,
onclick: () => status(s) onclick: () => status(s)
}, statusMap[s].title) }, statusMap[s].title)
@@ -279,14 +279,14 @@ const VariantsDemo = () => {
{ title: 'Event 3', detail: 'Description here', type: 'info', completed: false } { title: 'Event 3', detail: 'Description here', type: 'info', completed: false }
]; ];
return Div({ class: 'flex flex-col gap-8' }, [ return div({ class: 'flex flex-col gap-8' }, [
Div({ class: 'text-sm font-bold' }, 'Vertical Timeline'), div({ class: 'text-sm font-bold' }, 'Vertical Timeline'),
Timeline({ items: sampleItems }), Timeline({ items: sampleItems }),
Div({ class: 'text-sm font-bold mt-4' }, 'Horizontal Timeline'), div({ class: 'text-sm font-bold mt-4' }, 'Horizontal Timeline'),
Timeline({ items: sampleItems, vertical: false, class: 'min-w-[500px]' }), Timeline({ items: sampleItems, vertical: false, class: 'min-w-[500px]' }),
Div({ class: 'text-sm font-bold mt-4' }, 'Compact Timeline'), div({ class: 'text-sm font-bold mt-4' }, 'Compact Timeline'),
Timeline({ items: sampleItems, compact: true }) Timeline({ items: sampleItems, compact: true })
]); ]);
}; };

View File

@@ -25,20 +25,20 @@ Toast notification utility for displaying temporary messages that automatically
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Div({ class: 'flex flex-wrap gap-2 justify-center' }, [ return div({ class: 'flex flex-wrap gap-2 justify-center' }, [
Button({ button({
class: 'btn btn-info', class: 'btn btn-info',
onclick: () => Toast('This is an info message', 'alert-info', 3000) onclick: () => Toast('This is an info message', 'alert-info', 3000)
}, 'Info Toast'), }, 'Info Toast'),
Button({ button({
class: 'btn btn-success', class: 'btn btn-success',
onclick: () => Toast('Operation successful!', 'alert-success', 3000) onclick: () => Toast('Operation successful!', 'alert-success', 3000)
}, 'Success Toast'), }, 'Success Toast'),
Button({ button({
class: 'btn btn-warning', class: 'btn btn-warning',
onclick: () => Toast('Please check your input', 'alert-warning', 3000) onclick: () => Toast('Please check your input', 'alert-warning', 3000)
}, 'Warning Toast'), }, 'Warning Toast'),
Button({ button({
class: 'btn btn-error', class: 'btn btn-error',
onclick: () => Toast('An error occurred', 'alert-error', 3000) onclick: () => Toast('An error occurred', 'alert-error', 3000)
}, 'Error Toast') }, 'Error Toast')
@@ -58,20 +58,20 @@ mount(BasicDemo, '#demo-basic');
```javascript ```javascript
const DurationDemo = () => { const DurationDemo = () => {
return Div({ class: 'flex flex-wrap gap-2 justify-center' }, [ return div({ class: 'flex flex-wrap gap-2 justify-center' }, [
Button({ button({
class: 'btn btn-sm', class: 'btn btn-sm',
onclick: () => Toast('Short (1s)', 'alert-info', 1000) onclick: () => Toast('Short (1s)', 'alert-info', 1000)
}, '1 Second'), }, '1 Second'),
Button({ button({
class: 'btn btn-sm', class: 'btn btn-sm',
onclick: () => Toast('Normal (3s)', 'alert-success', 3000) onclick: () => Toast('Normal (3s)', 'alert-success', 3000)
}, '3 Seconds'), }, '3 Seconds'),
Button({ button({
class: 'btn btn-sm', class: 'btn btn-sm',
onclick: () => Toast('Long (5s)', 'alert-warning', 5000) onclick: () => Toast('Long (5s)', 'alert-warning', 5000)
}, '5 Seconds'), }, '5 Seconds'),
Button({ button({
class: 'btn btn-sm', class: 'btn btn-sm',
onclick: () => Toast('Very Long (8s)', 'alert-error', 8000) onclick: () => Toast('Very Long (8s)', 'alert-error', 8000)
}, '8 Seconds') }, '8 Seconds')
@@ -107,12 +107,12 @@ const InteractiveDemo = () => {
Toast(`${randomMessage} (${count()})`, randomType, 2000); Toast(`${randomMessage} (${count()})`, randomType, 2000);
}; };
return Div({ class: 'flex flex-col gap-4 items-center' }, [ return div({ class: 'flex flex-col gap-4 items-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: showRandomToast onclick: showRandomToast
}, 'Show Random Toast'), }, 'Show Random Toast'),
Div({ class: 'text-sm opacity-70' }, () => `Toasts shown: ${count()}`) div({ class: 'text-sm opacity-70' }, () => `Toasts shown: ${count()}`)
]); ]);
}; };
mount(InteractiveDemo, '#demo-interactive'); mount(InteractiveDemo, '#demo-interactive');
@@ -152,23 +152,23 @@ const FormToastDemo = () => {
Toast('Login successful! Redirecting...', 'alert-success', 2000); Toast('Login successful! Redirecting...', 'alert-success', 2000);
}; };
return Div({ class: 'flex flex-col gap-4 max-w-md mx-auto' }, [ return div({ class: 'flex flex-col gap-4 max-w-md mx-auto' }, [
Div({ class: 'text-lg font-bold text-center' }, 'Login Form'), div({ class: 'text-lg font-bold text-center' }, 'Login Form'),
Input({ input({
label: 'Email', label: 'Email',
type: 'email', type: 'email',
value: email, value: email,
placeholder: 'user@example.com', placeholder: 'user@example.com',
oninput: (e) => email(e.target.value) oninput: (e) => email(e.target.value)
}), }),
Input({ input({
label: 'Password', label: 'Password',
type: 'password', type: 'password',
value: password, value: password,
placeholder: 'Enter password', placeholder: 'Enter password',
oninput: (e) => password(e.target.value) oninput: (e) => password(e.target.value)
}), }),
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: handleSubmit onclick: handleSubmit
}, 'Login') }, 'Login')
@@ -206,20 +206,20 @@ const FeedbackDemo = () => {
Toast('All items saved!', 'alert-success', 2000); Toast('All items saved!', 'alert-success', 2000);
}; };
return Div({ class: 'flex flex-col gap-4' }, [ return div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex justify-between items-center' }, [ div({ class: 'flex justify-between items-center' }, [
Span({ class: 'font-bold' }, 'Items to Save'), span({ class: 'font-bold' }, 'Items to Save'),
Button({ button({
class: 'btn btn-sm btn-primary', class: 'btn btn-sm btn-primary',
onclick: saveAll onclick: saveAll
}, 'Save All') }, 'Save All')
]), ]),
Div({ class: 'flex flex-col gap-2' }, items().map(item => div({ class: 'flex flex-col gap-2' }, items().map(item =>
Div({ class: 'flex justify-between items-center p-3 bg-base-200 rounded-lg' }, [ div({ class: 'flex justify-between items-center p-3 bg-base-200 rounded-lg' }, [
Span({}, item.name), span({}, item.name),
item.saved item.saved
? Span({ class: 'badge badge-success' }, '✓ Saved') ? span({ class: 'badge badge-success' }, '✓ Saved')
: Button({ : button({
class: 'btn btn-xs btn-primary', class: 'btn btn-xs btn-primary',
onclick: () => saveItem(item.id) onclick: () => saveItem(item.id)
}, 'Save') }, 'Save')
@@ -259,16 +259,16 @@ const ErrorDemo = () => {
Toast('Request timeout (5s). Please check your connection.', 'alert-warning', 4000); Toast('Request timeout (5s). Please check your connection.', 'alert-warning', 4000);
}; };
return Div({ class: 'flex flex-wrap gap-3 justify-center' }, [ return div({ class: 'flex flex-wrap gap-3 justify-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: simulateApiCall onclick: simulateApiCall
}, 'Simulate API Call'), }, 'Simulate API Call'),
Button({ button({
class: 'btn btn-error', class: 'btn btn-error',
onclick: simulateNetworkError onclick: simulateNetworkError
}, 'Network Error'), }, 'Network Error'),
Button({ button({
class: 'btn btn-warning', class: 'btn btn-warning',
onclick: simulateTimeout onclick: simulateTimeout
}, 'Timeout') }, 'Timeout')
@@ -292,20 +292,20 @@ const CustomDemo = () => {
Toast(message, type, 3000); Toast(message, type, 3000);
}; };
return Div({ class: 'flex flex-wrap gap-2 justify-center' }, [ return div({ class: 'flex flex-wrap gap-2 justify-center' }, [
Button({ button({
class: 'btn btn-info', class: 'btn btn-info',
onclick: () => showCustomToast('alert-info', '📧 New email received from john@example.com') onclick: () => showCustomToast('alert-info', '📧 New email received from john@example.com')
}, 'Email'), }, 'Email'),
Button({ button({
class: 'btn btn-success', class: 'btn btn-success',
onclick: () => showCustomToast('alert-success', '💰 Payment of $49.99 completed') onclick: () => showCustomToast('alert-success', '💰 Payment of $49.99 completed')
}, 'Payment'), }, 'Payment'),
Button({ button({
class: 'btn btn-warning', class: 'btn btn-warning',
onclick: () => showCustomToast('alert-warning', '⚠️ Your session will expire in 5 minutes') onclick: () => showCustomToast('alert-warning', '⚠️ Your session will expire in 5 minutes')
}, 'Session Warning'), }, 'Session Warning'),
Button({ button({
class: 'btn btn-error', class: 'btn btn-error',
onclick: () => showCustomToast('alert-error', '🔒 Failed login attempt detected') onclick: () => showCustomToast('alert-error', '🔒 Failed login attempt detected')
}, 'Security Alert') }, 'Security Alert')
@@ -332,8 +332,8 @@ const MultipleDemo = () => {
setTimeout(() => Toast('Fourth message', 'alert-error', 3000), 1500); setTimeout(() => Toast('Fourth message', 'alert-error', 3000), 1500);
}; };
return Div({ class: 'flex justify-center' }, [ return div({ class: 'flex justify-center' }, [
Button({ button({
class: 'btn btn-primary', class: 'btn btn-primary',
onclick: showMultipleToasts onclick: showMultipleToasts
}, 'Show Multiple Toasts') }, 'Show Multiple Toasts')

View File

@@ -29,7 +29,7 @@ Tooltip supports all **daisyUI Tooltip classes**:
```javascript ```javascript
Tooltip({ tip: "This is a tooltip", class: "tooltip-primary" }, [ Tooltip({ tip: "This is a tooltip", class: "tooltip-primary" }, [
Button({ class: "btn" }, "Hover me") button({ class: "btn" }, "Hover me")
]); ]);
``` ```
@@ -46,15 +46,15 @@ Tooltip({ tip: "This is a tooltip", class: "tooltip-primary" }, [
```javascript ```javascript
const BasicDemo = () => { const BasicDemo = () => {
return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [ return div({ class: 'flex flex-wrap gap-4 justify-center' }, [
Tooltip({ tip: 'This is a tooltip' }, [ Tooltip({ tip: 'This is a tooltip' }, [
Button({ class: 'btn btn-primary' }, 'Hover me') button({ class: 'btn btn-primary' }, 'Hover me')
]), ]),
Tooltip({ tip: 'Tooltips can be placed on any element' }, [ Tooltip({ tip: 'Tooltips can be placed on any element' }, [
Span({ class: 'text-sm cursor-help border-b border-dashed' }, 'Help text') span({ class: 'text-sm cursor-help border-b border-dashed' }, 'Help text')
]), ]),
Tooltip({ tip: 'Icons can also have tooltips' }, [ Tooltip({ tip: 'Icons can also have tooltips' }, [
Span({ class: 'text-2xl' }, '') span({ class: 'text-2xl' }, '')
]) ])
]); ]);
}; };
@@ -72,18 +72,18 @@ mount(BasicDemo, '#demo-basic');
```javascript ```javascript
const PositionsDemo = () => { const PositionsDemo = () => {
return Div({ class: 'flex flex-wrap gap-8 justify-center' }, [ return div({ class: 'flex flex-wrap gap-8 justify-center' }, [
Tooltip({ tip: 'Top tooltip', class: 'tooltip-top' }, [ Tooltip({ tip: 'Top tooltip', class: 'tooltip-top' }, [
Button({ class: 'btn btn-sm' }, 'Top') button({ class: 'btn btn-sm' }, 'Top')
]), ]),
Tooltip({ tip: 'Bottom tooltip', class: 'tooltip-bottom' }, [ Tooltip({ tip: 'Bottom tooltip', class: 'tooltip-bottom' }, [
Button({ class: 'btn btn-sm' }, 'Bottom') button({ class: 'btn btn-sm' }, 'Bottom')
]), ]),
Tooltip({ tip: 'Left tooltip', class: 'tooltip-left' }, [ Tooltip({ tip: 'Left tooltip', class: 'tooltip-left' }, [
Button({ class: 'btn btn-sm' }, 'Left') button({ class: 'btn btn-sm' }, 'Left')
]), ]),
Tooltip({ tip: 'Right tooltip', class: 'tooltip-right' }, [ Tooltip({ tip: 'Right tooltip', class: 'tooltip-right' }, [
Button({ class: 'btn btn-sm' }, 'Right') button({ class: 'btn btn-sm' }, 'Right')
]) ])
]); ]);
}; };
@@ -101,18 +101,18 @@ mount(PositionsDemo, '#demo-positions');
```javascript ```javascript
const IconsDemo = () => { const IconsDemo = () => {
return Div({ class: 'flex flex-wrap gap-8 justify-center' }, [ return div({ class: 'flex flex-wrap gap-8 justify-center' }, [
Tooltip({ tip: 'Save document' }, [ Tooltip({ tip: 'Save document' }, [
Button({ class: 'btn btn-ghost btn-circle' }, '💾') button({ class: 'btn btn-ghost btn-circle' }, '💾')
]), ]),
Tooltip({ tip: 'Edit item' }, [ Tooltip({ tip: 'Edit item' }, [
Button({ class: 'btn btn-ghost btn-circle' }, '✏️') button({ class: 'btn btn-ghost btn-circle' }, '✏️')
]), ]),
Tooltip({ tip: 'Delete permanently' }, [ Tooltip({ tip: 'Delete permanently' }, [
Button({ class: 'btn btn-ghost btn-circle text-error' }, '🗑️') button({ class: 'btn btn-ghost btn-circle text-error' }, '🗑️')
]), ]),
Tooltip({ tip: 'Settings' }, [ Tooltip({ tip: 'Settings' }, [
Button({ class: 'btn btn-ghost btn-circle' }, '⚙️') button({ class: 'btn btn-ghost btn-circle' }, '⚙️')
]) ])
]); ]);
}; };
@@ -133,20 +133,20 @@ const FormDemo = () => {
const username = $(''); const username = $('');
const email = $(''); const email = $('');
return Div({ class: 'flex flex-col gap-4 max-w-md mx-auto' }, [ return div({ class: 'flex flex-col gap-4 max-w-md mx-auto' }, [
Div({ class: 'flex items-center gap-2' }, [ div({ class: 'flex items-center gap-2' }, [
Input({ input({
label: 'Username', label: 'Username',
value: username, value: username,
placeholder: 'Choose a username', placeholder: 'Choose a username',
oninput: (e) => username(e.target.value) oninput: (e) => username(e.target.value)
}), }),
Tooltip({ tip: 'Must be at least 3 characters, letters and numbers only' }, [ Tooltip({ tip: 'Must be at least 3 characters, letters and numbers only' }, [
Span({ class: 'cursor-help text-info' }, '?') span({ class: 'cursor-help text-info' }, '?')
]) ])
]), ]),
Div({ class: 'flex items-center gap-2' }, [ div({ class: 'flex items-center gap-2' }, [
Input({ input({
label: 'Email', label: 'Email',
type: 'email', type: 'email',
value: email, value: email,
@@ -154,7 +154,7 @@ const FormDemo = () => {
oninput: (e) => email(e.target.value) oninput: (e) => email(e.target.value)
}), }),
Tooltip({ tip: 'We\'ll never share your email with anyone' }, [ Tooltip({ tip: 'We\'ll never share your email with anyone' }, [
Span({ class: 'cursor-help text-info' }, '?') span({ class: 'cursor-help text-info' }, '?')
]) ])
]) ])
]); ]);
@@ -182,19 +182,19 @@ const InteractiveDemo = () => {
}, 2000); }, 2000);
}; };
return Div({ class: 'flex flex-col gap-4 items-center' }, [ return div({ class: 'flex flex-col gap-4 items-center' }, [
Tooltip({ tip: () => tooltipText() }, [ Tooltip({ tip: () => tooltipText() }, [
Button({ button({
class: 'btn btn-primary btn-lg', class: 'btn btn-primary btn-lg',
onclick: () => Toast('Button clicked!', 'alert-info', 2000) onclick: () => Toast('Button clicked!', 'alert-info', 2000)
}, 'Interactive Button') }, 'Interactive Button')
]), ]),
Div({ class: 'flex gap-2 flex-wrap justify-center mt-4' }, [ div({ class: 'flex gap-2 flex-wrap justify-center mt-4' }, [
Button({ button({
class: 'btn btn-xs', class: 'btn btn-xs',
onclick: () => updateTooltip('You clicked the button!') onclick: () => updateTooltip('You clicked the button!')
}, 'Change Tooltip'), }, 'Change Tooltip'),
Button({ button({
class: 'btn btn-xs', class: 'btn btn-xs',
onclick: () => updateTooltip('Try hovering now!') onclick: () => updateTooltip('Try hovering now!')
}, 'Change Again') }, 'Change Again')
@@ -215,28 +215,28 @@ mount(InteractiveDemo, '#demo-interactive');
```javascript ```javascript
const RichDemo = () => { const RichDemo = () => {
return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [ return div({ class: 'flex flex-wrap gap-4 justify-center' }, [
Tooltip({ Tooltip({
tip: Div({ class: 'text-left p-1' }, [ tip: div({ class: 'text-left p-1' }, [
Div({ class: 'font-bold' }, 'User Info'), div({ class: 'font-bold' }, 'User Info'),
Div({ class: 'text-xs' }, 'John Doe'), div({ class: 'text-xs' }, 'John Doe'),
Div({ class: 'text-xs' }, 'john@example.com'), div({ class: 'text-xs' }, 'john@example.com'),
Div({ class: 'badge badge-xs badge-primary mt-1' }, 'Admin') div({ class: 'badge badge-xs badge-primary mt-1' }, 'Admin')
]) ])
}, [ }, [
Button({ class: 'btn btn-outline' }, 'User Profile') button({ class: 'btn btn-outline' }, 'User Profile')
]), ]),
Tooltip({ Tooltip({
tip: Div({ class: 'text-left p-1' }, [ tip: div({ class: 'text-left p-1' }, [
Div({ class: 'font-bold flex items-center gap-1' }, [ div({ class: 'font-bold flex items-center gap-1' }, [
Span({}, '⚠️'), span({}, '⚠️'),
Span({}, 'System Status') span({}, 'System Status')
]), ]),
Div({ class: 'text-xs' }, 'All systems operational'), div({ class: 'text-xs' }, 'All systems operational'),
Div({ class: 'text-xs text-success' }, '✓ 99.9% uptime') div({ class: 'text-xs text-success' }, '✓ 99.9% uptime')
]) ])
}, [ }, [
Button({ class: 'btn btn-outline' }, 'System Status') button({ class: 'btn btn-outline' }, 'System Status')
]) ])
]); ]);
}; };
@@ -254,27 +254,27 @@ mount(RichDemo, '#demo-rich');
```javascript ```javascript
const ColorsDemo = () => { const ColorsDemo = () => {
return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [ return div({ class: 'flex flex-wrap gap-4 justify-center' }, [
Tooltip({ tip: 'Primary tooltip', class: 'tooltip-primary' }, [ Tooltip({ tip: 'Primary tooltip', class: 'tooltip-primary' }, [
Button({ class: 'btn btn-primary btn-sm' }, 'Primary') button({ class: 'btn btn-primary btn-sm' }, 'Primary')
]), ]),
Tooltip({ tip: 'Secondary tooltip', class: 'tooltip-secondary' }, [ Tooltip({ tip: 'Secondary tooltip', class: 'tooltip-secondary' }, [
Button({ class: 'btn btn-secondary btn-sm' }, 'Secondary') button({ class: 'btn btn-secondary btn-sm' }, 'Secondary')
]), ]),
Tooltip({ tip: 'Accent tooltip', class: 'tooltip-accent' }, [ Tooltip({ tip: 'Accent tooltip', class: 'tooltip-accent' }, [
Button({ class: 'btn btn-accent btn-sm' }, 'Accent') button({ class: 'btn btn-accent btn-sm' }, 'Accent')
]), ]),
Tooltip({ tip: 'Info tooltip', class: 'tooltip-info' }, [ Tooltip({ tip: 'Info tooltip', class: 'tooltip-info' }, [
Button({ class: 'btn btn-info btn-sm' }, 'Info') button({ class: 'btn btn-info btn-sm' }, 'Info')
]), ]),
Tooltip({ tip: 'Success tooltip', class: 'tooltip-success' }, [ Tooltip({ tip: 'Success tooltip', class: 'tooltip-success' }, [
Button({ class: 'btn btn-success btn-sm' }, 'Success') button({ class: 'btn btn-success btn-sm' }, 'Success')
]), ]),
Tooltip({ tip: 'Warning tooltip', class: 'tooltip-warning' }, [ Tooltip({ tip: 'Warning tooltip', class: 'tooltip-warning' }, [
Button({ class: 'btn btn-warning btn-sm' }, 'Warning') button({ class: 'btn btn-warning btn-sm' }, 'Warning')
]), ]),
Tooltip({ tip: 'Error tooltip', class: 'tooltip-error' }, [ Tooltip({ tip: 'Error tooltip', class: 'tooltip-error' }, [
Button({ class: 'btn btn-error btn-sm' }, 'Error') button({ class: 'btn btn-error btn-sm' }, 'Error')
]) ])
]); ]);
}; };
@@ -292,25 +292,25 @@ mount(ColorsDemo, '#demo-colors');
```javascript ```javascript
const AllPositionsDemo = () => { const AllPositionsDemo = () => {
return Div({ class: 'grid grid-cols-3 gap-4 justify-items-center' }, [ return div({ class: 'grid grid-cols-3 gap-4 justify-items-center' }, [
Div({ class: 'col-start-2' }, [ div({ class: 'col-start-2' }, [
Tooltip({ tip: 'Top tooltip', class: 'tooltip-top' }, [ Tooltip({ tip: 'Top tooltip', class: 'tooltip-top' }, [
Button({ class: 'btn btn-sm w-24' }, 'Top') button({ class: 'btn btn-sm w-24' }, 'Top')
]) ])
]), ]),
Div({ class: 'col-start-1 row-start-2' }, [ div({ class: 'col-start-1 row-start-2' }, [
Tooltip({ tip: 'Left tooltip', class: 'tooltip-left' }, [ Tooltip({ tip: 'Left tooltip', class: 'tooltip-left' }, [
Button({ class: 'btn btn-sm w-24' }, 'Left') button({ class: 'btn btn-sm w-24' }, 'Left')
]) ])
]), ]),
Div({ class: 'col-start-3 row-start-2' }, [ div({ class: 'col-start-3 row-start-2' }, [
Tooltip({ tip: 'Right tooltip', class: 'tooltip-right' }, [ Tooltip({ tip: 'Right tooltip', class: 'tooltip-right' }, [
Button({ class: 'btn btn-sm w-24' }, 'Right') button({ class: 'btn btn-sm w-24' }, 'Right')
]) ])
]), ]),
Div({ class: 'col-start-2 row-start-3' }, [ div({ class: 'col-start-2 row-start-3' }, [
Tooltip({ tip: 'Bottom tooltip', class: 'tooltip-bottom' }, [ Tooltip({ tip: 'Bottom tooltip', class: 'tooltip-bottom' }, [
Button({ class: 'btn btn-sm w-24' }, 'Bottom') button({ class: 'btn btn-sm w-24' }, 'Bottom')
]) ])
]) ])
]); ]);

View File

@@ -33,11 +33,11 @@ const App = () => {
return h('div', { class: 'p-8 max-w-md mx-auto' }, [ return h('div', { class: 'p-8 max-w-md mx-auto' }, [
h('h1', { class: 'text-2xl font-bold mb-4' }, 'SigProUI Demo'), h('h1', { class: 'text-2xl font-bold mb-4' }, 'SigProUI Demo'),
Input({ input({
placeholder: 'Enter your name...' placeholder: 'Enter your name...'
}), }),
Button({ button({
class: 'btn-primary mt-4', class: 'btn-primary mt-4',
onclick: () => count(count() + 1) onclick: () => count(count() + 1)
}, () => `Clicks: ${count()}`), }, () => `Clicks: ${count()}`),
@@ -86,12 +86,12 @@ Simply add the script tag and start using SigProUI:
return h('div', { class: 'max-w-md mx-auto p-4' }, [ return h('div', { class: 'max-w-md mx-auto p-4' }, [
h('h1', { class: 'text-2xl font-bold mb-4' }, 'SigProUI Demo'), h('h1', { class: 'text-2xl font-bold mb-4' }, 'SigProUI Demo'),
Input({ input({
value: name, value: name,
placeholder: 'Enter your name...' placeholder: 'Enter your name...'
}), }),
Button({ button({
class: 'btn-primary mt-4', class: 'btn-primary mt-4',
onclick: () => count(count() + 1) onclick: () => count(count() + 1)
}, () => `Clicks: ${count()}`), }, () => `Clicks: ${count()}`),
@@ -125,8 +125,8 @@ When you install SigProUI, you get:
>For more information about SigPro Core visit official Docs [SigPro Docs](https://natxocc.github.io/sigpro/#/) >For more information about SigPro Core visit official Docs [SigPro Docs](https://natxocc.github.io/sigpro/#/)
### UI Components ### UI Components
- `Button()` - Styled button with DaisyUI - `button()` - Styled button with DaisyUI
- `Input()` - Form input with floating labels - `input()` - Form input with floating labels
- `Alert()` - Alert messages - `Alert()` - Alert messages
- `Modal()` - Modal dialogs - `Modal()` - Modal dialogs
- `Table()` - Data tables - `Table()` - Data tables
@@ -147,8 +147,8 @@ import { tt, Locale } from 'sigpro-ui';
Locale('en'); Locale('en');
// Use translations // Use translations
const closeButton = Button({}, tt('close')()); const closeButton = button({}, tt('close')());
const searchPlaceholder = Input({ placeholder: tt('search')() }); const searchPlaceholder = input({ placeholder: tt('search')() });
``` ```
## TypeScript Support ## TypeScript Support
@@ -159,7 +159,7 @@ SigProUI includes TypeScript definitions. Import types as needed:
import { Button, Input, type ButtonProps, type InputProps } from 'sigpro-ui'; import { Button, Input, type ButtonProps, type InputProps } from 'sigpro-ui';
const MyButton: React.FC<ButtonProps> = (props) => { const MyButton: React.FC<ButtonProps> = (props) => {
return Button(props, 'Click me'); return button(props, 'Click me');
}; };
``` ```

View File

@@ -18,8 +18,8 @@ import "sigpro-ui/css";
| Component | Purpose | Basic Example | | Component | Purpose | Basic Example |
| :--- | :--- | :--- | | :--- | :--- | :--- |
| **Button** | Styled button with DaisyUI | `Button({ class: "btn-primary" }, "Submit")` | | **Button** | Styled button with DaisyUI | `button({ class: "btn-primary" }, "Submit")` |
| **Input** | Reactive text field with validation | `Input({ value: $name, validate: (v) => !v ? "Required" : "" })` | | **Input** | Reactive text field with validation | `input({ value: $name, validate: (v) => !v ? "Required" : "" })` |
| **Select** | Dropdown selection menu | `Select({ options: ["Admin", "User"], value: $role })` | | **Select** | Dropdown selection menu | `Select({ options: ["Admin", "User"], value: $role })` |
| **Checkbox** | Binary toggle (boolean) | `Checkbox({ label: "Active", checked: $isActive })` | | **Checkbox** | Binary toggle (boolean) | `Checkbox({ label: "Active", checked: $isActive })` |
| **Table** | Data grid with column rendering | `Table({ items: $data, columns: [...] })` | | **Table** | Data grid with column rendering | `Table({ items: $data, columns: [...] })` |
@@ -37,9 +37,9 @@ import "sigpro-ui/css";
| Component | Description | Example | | Component | Description | Example |
| :--- | :--- | :--- | | :--- | :--- | :--- |
| **Input** | Text input with floating label, validation, password toggle | `Input({ label: "Email", type: "email", value: $email, validate: validateEmail })` | | **Input** | Text input with floating label, validation, password toggle | `input({ label: "Email", type: "email", value: $email, validate: validateEmail })` |
| **Select** | Dropdown selector | `Select({ label: "Role", options: ["Admin", "User"], value: $role })` | | **Select** | Dropdown selector | `Select({ label: "Role", options: ["Admin", "User"], value: $role })` |
| **Autocomplete** | Searchable dropdown with filtering | `Autocomplete({ label: "Country", options: countryList, value: $country })` | | **Autocomplete** | Searchable dropdown with filtering | `autocomplete({ label: "Country", options: countryList, value: $country })` |
| **Datepicker** | Date picker (single or range mode) | `Datepicker({ label: "Date", value: $date, range: false })` | | **Datepicker** | Date picker (single or range mode) | `Datepicker({ label: "Date", value: $date, range: false })` |
| **Colorpicker** | Visual color picker with palette | `Colorpicker({ label: "Theme", value: $color })` | | **Colorpicker** | Visual color picker with palette | `Colorpicker({ label: "Theme", value: $color })` |
| **Checkbox** | Checkbox or toggle switch | `Checkbox({ label: "Remember me", value: $remember })` | | **Checkbox** | Checkbox or toggle switch | `Checkbox({ label: "Remember me", value: $remember })` |
@@ -57,7 +57,7 @@ The `Input` component supports real-time validation via the `validate` prop:
```javascript ```javascript
const email = $(''); const email = $('');
Input({ input({
type: 'email', type: 'email',
value: email, value: email,
placeholder: 'Enter your email', placeholder: 'Enter your email',
@@ -90,7 +90,7 @@ Input({
| **Stat** | Statistical data blocks (KPIs) | `Stat({ label: "Total", value: "1.2k", desc: "Monthly" })` | | **Stat** | Statistical data blocks (KPIs) | `Stat({ label: "Total", value: "1.2k", desc: "Monthly" })` |
| **Timeline** | Vertical/horizontal timeline | `Timeline({ items: [{ title: "Step 1", detail: "Completed" }] })` | | **Timeline** | Vertical/horizontal timeline | `Timeline({ items: [{ title: "Step 1", detail: "Completed" }] })` |
| **Stack** | Stacked elements | `Stack({}, [Card1, Card2, Card3])` | | **Stack** | Stacked elements | `Stack({}, [Card1, Card2, Card3])` |
| **Indicator** | Badge on corner of element | `Indicator({ value: () => count() }, Button(...))` | | **Indicator** | Badge on corner of element | `Indicator({ value: () => count() }, button(...))` |
--- ---
@@ -101,7 +101,7 @@ Input({
| **Alert** | Inline contextual notification | `Alert({ type: "success" }, "Changes saved!")` | | **Alert** | Inline contextual notification | `Alert({ type: "success" }, "Changes saved!")` |
| **Modal** | Dialog overlay | `Modal({ open: $isOpen, title: "Confirm" }, "Are you sure?")` | | **Modal** | Dialog overlay | `Modal({ open: $isOpen, title: "Confirm" }, "Are you sure?")` |
| **Toast** | Floating notification (auto-stacking) | `Toast("Action completed", "alert-info", 3000)` | | **Toast** | Floating notification (auto-stacking) | `Toast("Action completed", "alert-info", 3000)` |
| **Tooltip** | Hover tooltip wrapper | `Tooltip({ tip: "Help text", ui: "tooltip-top" }, Button(...))` | | **Tooltip** | Hover tooltip wrapper | `Tooltip({ tip: "Help text", ui: "tooltip-top" }, button(...))` |
--- ---
@@ -115,7 +115,7 @@ Input({
| **Tabs** | Content switching | `Tabs({ items: [{ label: "Tab1", content: Panel1 }] })` | | **Tabs** | Content switching | `Tabs({ items: [{ label: "Tab1", content: Panel1 }] })` |
| **Accordion** | Collapsible sections | `Accordion({ title: "Details" }, "Hidden content")` | | **Accordion** | Collapsible sections | `Accordion({ title: "Details" }, "Hidden content")` |
| **Dropdown** | Contextual menus | `Dropdown({ label: "Options" }, [MenuLink("Edit")])` | | **Dropdown** | Contextual menus | `Dropdown({ label: "Options" }, [MenuLink("Edit")])` |
| **Fieldset** | Form grouping with legend | `Fieldset({ legend: "Personal Info" }, [Input(...)])` | | **Fieldset** | Form grouping with legend | `Fieldset({ legend: "Personal Info" }, [input(...)])` |
--- ---
@@ -124,7 +124,7 @@ Input({
| Component | Description | Example | | Component | Description | Example |
| :--- | :--- | :--- | | :--- | :--- | :--- |
| **Fab** | Floating Action Button with actions | `Fab({ icon: "+", actions: [{ label: "Add", onclick: add }] })` | | **Fab** | Floating Action Button with actions | `Fab({ icon: "+", actions: [{ label: "Add", onclick: add }] })` |
| **Indicator** | Badge indicator wrapper | `Indicator({ value: () => unread() }, Button(...))` | | **Indicator** | Badge indicator wrapper | `Indicator({ value: () => unread() }, button(...))` |
--- ---
@@ -150,7 +150,7 @@ const closeText = tt("close"); // "Close" or "Cerrar"
2. **DaisyUI v5**: Pass any daisyUI styling via the `class` attribute. 2. **DaisyUI v5**: Pass any daisyUI styling via the `class` attribute.
```javascript ```javascript
Button({ class: "btn-primary btn-sm rounded-full shadow-lg" }, "Click") button({ class: "btn-primary btn-sm rounded-full shadow-lg" }, "Click")
``` ```
3. **Zero Imports (Global Mode)**: After calling `UI()`, all components are attached to `window`. No manual imports needed. 3. **Zero Imports (Global Mode)**: After calling `UI()`, all components are attached to `window`. No manual imports needed.
@@ -166,7 +166,7 @@ const closeText = tt("close"); // "Close" or "Cerrar"
```javascript ```javascript
const name = $(""); const name = $("");
Input({ input({
value: name, value: name,
placeholder: "Name", placeholder: "Name",
validate: (value) => { validate: (value) => {
@@ -203,7 +203,7 @@ Modal({
open: showModal, open: showModal,
title: "Delete Item", title: "Delete Item",
buttons: [ buttons: [
Button({ class: "btn-error", onclick: () => { deleteItem(); showModal(false); } }, "Delete") button({ class: "btn-error", onclick: () => { deleteItem(); showModal(false); } }, "Delete")
] ]
}, "Are you sure you want to delete this item?"); }, "Are you sure you want to delete this item?");
``` ```

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12
index.d.ts vendored
View File

@@ -71,7 +71,7 @@ declare module 'sigpro-ui' {
label?: string | (() => string); label?: string | (() => string);
placeholder?: string | (() => string); placeholder?: string | (() => string);
} }
function Autocomplete(props: AutocompleteProps): HTMLElement; function autocomplete(props: AutocompleteProps): HTMLElement;
// Badge // Badge
interface BadgeProps extends BaseProps, EventProps {} interface BadgeProps extends BaseProps, EventProps {}
@@ -83,7 +83,7 @@ declare module 'sigpro-ui' {
loading?: boolean | (() => boolean); loading?: boolean | (() => boolean);
icon?: string | (() => string) | HTMLElement; icon?: string | (() => string) | HTMLElement;
} }
function Button(props: ButtonProps, children: ComponentChildren): HTMLElement; function button(props: ButtonProps, children: ComponentChildren): HTMLElement;
// Checkbox // Checkbox
interface CheckboxProps extends BaseProps, EventProps { interface CheckboxProps extends BaseProps, EventProps {
@@ -160,7 +160,7 @@ declare module 'sigpro-ui' {
interface FieldsetProps extends BaseProps, EventProps { interface FieldsetProps extends BaseProps, EventProps {
legend?: string | (() => string); legend?: string | (() => string);
} }
function Fieldset(props: FieldsetProps, children: ComponentChildren): HTMLElement; function fieldset(props: FieldsetProps, children: ComponentChildren): HTMLElement;
// Fileinput // Fileinput
interface FileinputProps extends BaseProps, EventProps { interface FileinputProps extends BaseProps, EventProps {
@@ -188,7 +188,7 @@ declare module 'sigpro-ui' {
validate?: (value: string) => string | null | undefined; validate?: (value: string) => string | null | undefined;
label?: string | (() => string); label?: string | (() => string);
} }
function Input(props: InputProps): HTMLElement; function input(props: InputProps): HTMLElement;
// Label // Label
interface LabelProps extends BaseProps, EventProps { interface LabelProps extends BaseProps, EventProps {
@@ -197,7 +197,7 @@ declare module 'sigpro-ui' {
error?: string | (() => string); error?: string | (() => string);
required?: boolean; required?: boolean;
} }
function Label(props: LabelProps, children: ComponentChildren): HTMLElement; function label(props: LabelProps, children: ComponentChildren): HTMLElement;
// List // List
interface ListProps<T = any> extends BaseProps, EventProps { interface ListProps<T = any> extends BaseProps, EventProps {
@@ -276,7 +276,7 @@ declare module 'sigpro-ui' {
items?: SelectOption[] | (() => SelectOption[]); items?: SelectOption[] | (() => SelectOption[]);
value?: Signal<string | number> | string | number; value?: Signal<string | number> | string | number;
} }
function Select(props: SelectProps): HTMLElement; function select(props: SelectProps): HTMLElement;
// Stack // Stack
interface StackProps extends BaseProps, EventProps {} interface StackProps extends BaseProps, EventProps {}

View File

@@ -1,15 +1,15 @@
import * as AccordionModule from './components/accordion.js'; import * as AccordionModule from './components/accordion.js';
import * as AlertModule from './components/alert.js'; import * as AlertModule from './components/alert.js';
import * as AutocompleteModule from './components/autocomplete.js'; import * as AutocompleteModule from './components/Autocomplete.js';
import * as BadgeModule from './components/badge.js'; import * as BadgeModule from './components/badge.js';
import * as ButtonModule from './components/button.js'; import * as ButtonModule from './components/button.js';
import * as CalendarModule from './components/calendar.js'; import * as CalendarModule from './components/Calendar.js';
import * as CardModule from './components/card.js'; import * as CardModule from './components/card.js';
import * as CarouselModule from './components/carousel.js'; import * as CarouselModule from './components/carousel.js';
import * as ChatModule from './components/chat.js'; import * as ChatModule from './components/chat.js';
import * as CheckboxModule from './components/checkbox.js'; import * as CheckboxModule from './components/checkbox.js';
import * as ColorpickerModule from './components/colorpicker.js'; import * as ColorpickerModule from './components/colorpicker.js';
import * as DatepickerModule from './components/datepicker.js'; import * as DatepickerModule from './components/Datepicker.js';
import * as DrawerModule from './components/drawer.js'; import * as DrawerModule from './components/drawer.js';
import * as DropdownModule from './components/dropdown.js'; import * as DropdownModule from './components/dropdown.js';
import * as FabModule from './components/fab.js'; import * as FabModule from './components/fab.js';
@@ -17,7 +17,7 @@ import * as FieldsetModule from './components/fieldset.js';
import * as FileinputModule from './components/fileinput.js'; import * as FileinputModule from './components/fileinput.js';
import * as IconModule from './components/icon.js'; import * as IconModule from './components/icon.js';
import * as IndicatorModule from './components/indicator.js'; import * as IndicatorModule from './components/indicator.js';
import * as InputModule from './components/input.js'; import * as InputModule from './components/Input.js';
import * as KdbModule from './components/kbd.js'; import * as KdbModule from './components/kbd.js';
// import * as ListModule from './components/List.js'; // import * as ListModule from './components/List.js';
import * as LoadingModule from './components/loading.js'; import * as LoadingModule from './components/loading.js';

View File

@@ -60,74 +60,38 @@
font-size: 14px; font-size: 14px;
} }
.input, .input,
.label,
.select, .select,
.textarea { .textarea {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:focus, &:focus,
&:focus-within { &:focus-within {
outline: 1px solid transparent !important; outline: none !important;
outline-offset: 1px !important; box-shadow: 0 0 4px 0px;
} }
&:hover:not(:focus) { &:hover:not(:focus) {
background-color: oklch(from var(--color-base-100) calc(l - 0.03) c h); background-color: oklch(from var(--color-base-100) calc(l - 0.03) c h);
} }
&:focus {
--focus-color: var(--color-primary);
&[class*="-secondary"] {
--focus-color: var(--color-secondary);
}
&[class*="-accent"] {
--focus-color: var(--color-accent);
}
&[class*="-neutral"] {
--focus-color: var(--color-neutral);
}
&[class*="-ghost"] {
--focus-color: var(--color-base-content);
}
&[class*="-info"] {
--focus-color: var(--color-info);
}
&[class*="-success"] {
--focus-color: var(--color-success);
}
&[class*="-warning"] {
--focus-color: var(--color-warning);
}
&[class*="-error"] {
--focus-color: var(--color-error);
}
background-color: oklch(from var(--focus-color) l c h / 0.05);
border-color: var(--focus-color);
box-shadow: 0 0 0 4px oklch(from var(--focus-color) l c h / 0.25);
&[class*="-ghost"] {
border-width: 1px;
}
}
} }
.floating-label span { .floating-label span {
color: oklch(30% 0.01 260); /* Gris más oscuro (30% es más oscuro que 45%) */ color: oklch(30% 0.01 260);
font-size: 1.1rem; /* text-base: más grande que 0.875rem */ font-size: 1.1rem;
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.floating-label:focus-within span { .floating-label:focus-within span {
color: oklch(25% 0.02 260); /* Aún más oscuro al enfocar */ color: oklch(25% 0.02 260);
font-size: 1.1rem; /* Mantiene el mismo tamaño */ font-size: 1.1rem;
} }
.floating-label:has(input:not(:placeholder-shown)) span { .floating-label:has(input:not(:placeholder-shown)) span {
color: oklch(28% 0.01 260); /* Gris oscuro cuando tiene valor */ color: oklch(28% 0.01 260);
font-size: 1.1rem; /* Mantiene el mismo tamaño */ font-size: 1.1rem;
} }
.tab-content-inner { .tab-content-inner {
@@ -135,6 +99,16 @@
transform-origin: top; transform-origin: top;
} }
.input-content {
position: absolute; /* Lo saca del flujo para que no empuje nada */
top: 100%; /* Lo pega justo al borde inferior del input */
left: 0;
width: 100%; /* Para que mida lo mismo que el input */
z-index: 100; /* Para que pase por encima de otros botones/inputs */
background: white; /* Para que no sea transparente y se lea bien */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* Opcional: para darle profundidad */
}
@keyframes tabFadeIn { @keyframes tabFadeIn {
from { from {
opacity: 0; opacity: 0;
@@ -146,6 +120,34 @@
} }
} }
@layer utilities {
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(-8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fade-out {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0;
transform: translateY(-8px);
}
}
.animate-fade-in {
animation: fade-in 0.15s ease-out forwards;
}
}
/* @layer utilities { /* @layer utilities {
button { button {
@apply btn; @apply btn;

View File

@@ -65,7 +65,7 @@ export const Autocomplete = (props) => {
}; };
return h("div", { class: 'relative w-full' }, [ return h("div", { class: 'relative w-full' }, [
Input({ input({
label, label,
class: className, class: className,
placeholder: placeholder, placeholder: placeholder,

View File

@@ -43,7 +43,7 @@ export const Datepicker = (props) => {
}; };
return h("div", { class: ui('relative w-full', className) }, [ return h("div", { class: ui('relative w-full', className) }, [
Input({ input({
label, label,
placeholder: placeholder || (isRangeMode() ? "Seleccionar rango..." : "Seleccionar fecha..."), placeholder: placeholder || (isRangeMode() ? "Seleccionar rango..." : "Seleccionar fecha..."),
value: displayValue, value: displayValue,

View File

@@ -23,7 +23,7 @@ export const InputPopover = (props) => {
const toggle = () => isOpen(!isOpen()); const toggle = () => isOpen(!isOpen());
return h("div", { class: ui("relative w-full", className) }, [ return h("div", { class: ui("relative w-full", className) }, [
Input({ input({
label, label,
placeholder, placeholder,
value: displayValue, value: displayValue,

View File

@@ -53,7 +53,7 @@ export const Modal = (props, children) => {
h("div", { class: "modal-action" }, [ h("div", { class: "modal-action" }, [
h("form", { method: "dialog", class: "flex gap-2" }, [ h("form", { method: "dialog", class: "flex gap-2" }, [
...(Array.isArray(buttons) ? buttons : [buttons]).filter(Boolean), ...(Array.isArray(buttons) ? buttons : [buttons]).filter(Boolean),
Button({ type: "submit" }, "close") button({ type: "submit" }, "close")
]) ])
]) ])
]), ]),

View File

@@ -55,7 +55,7 @@ export const Toast = (message, type = "alert-success", duration = 3500) => {
}, },
[ [
h("span", {}, [typeof message === "function" ? message() : message]), h("span", {}, [typeof message === "function" ? message() : message]),
Button({ button({
class: "btn-xs btn-circle btn-ghost", class: "btn-xs btn-circle btn-ghost",
onclick: close onclick: close
}, closeIcon) }, closeIcon)