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 show = $(false);
return Button(
return button(
{
class: "btn-primary",
onclick: () => show(true)
@@ -77,7 +77,7 @@ import "sigpro-ui/css";
// All components (Button, Table, Input, Alert, etc.) are now globally available.
// 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 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"),
Button({
button({
class: "btn-primary",
onclick: () => {
count(c => c + 1);
@@ -148,7 +148,7 @@ import { tt, Locale } from "sigpro-ui";
Locale('en');
// Use translations
const closeButton = Button({}, tt('close')());
const closeButton = button({}, tt('close')());
```
---

View File

@@ -1,7 +1,7 @@
// components/Accordion.js
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)}`;
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 ?? ''}` }, [
h("input", { type: "radio", name, checked: item.open }),
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 ?? ''}` }, [
h("input", { type: "radio", name, checked: props.open }),
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
import { h } from "sigpro";
const colors = [""]
export const Badge = (props, children) => {
children === undefined && (children = props, props = {});
return h("span", { ...props, class: `badge ${props.class ?? ''}` }, children);

View File

@@ -1,6 +1,6 @@
// components/Datepicker.js
import { $, h, when, watch } from "sigpro";
import { Calendar } from "./calendar.js";
import { Calendar } from "./Calendar.js";
export const Datepicker = (props) => {
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

@@ -3,4 +3,4 @@ import { h } from "sigpro";
export const Button = (props, children) => {
children === undefined && (children = props, props = {});
return h("button", { ...props, class: `btn ${props.class ?? ''}` }, children);
};
};

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: calc(var(--spacing) * 0);
}
.top-1\/2 {
top: calc(1 / 2 * 100%);
}
.top-2 {
top: calc(var(--spacing) * 2);
}
@@ -3122,6 +3125,9 @@
.right-1\/4 {
right: calc(1 / 4 * 100%);
}
.right-2 {
right: calc(var(--spacing) * 2);
}
.right-3 {
right: calc(var(--spacing) * 3);
}
@@ -4153,6 +4159,19 @@
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");
}
.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\] {
display: inline-block;
width: 1em;
@@ -4831,6 +4850,11 @@
width: 100%;
}
}
.loading-xs {
@layer daisyui.l1.l2 {
width: calc(var(--size-selector, 0.25rem) * 4);
}
}
.w-3\.5 {
width: calc(var(--spacing) * 3.5);
}
@@ -4941,6 +4965,10 @@
--tw-translate-x: 100%;
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 {
--tw-translate-y: calc(var(--spacing) * 2);
translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -5395,12 +5423,6 @@
.border-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-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 {
@media (hover: hover) {
@@ -7128,48 +7143,15 @@
:root {
font-size: 14px;
}
.input, .select, .textarea {
.input, .label, .select, .textarea {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:focus, &:focus-within {
outline: 1px solid transparent !important;
outline-offset: 1px !important;
outline: none !important;
box-shadow: 0 0 4px 0px;
}
&:hover:not(:focus) {
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 {
color: oklch(30% 0.01 260);
@@ -7188,6 +7170,15 @@
animation: tabFadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
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 {
from {
opacity: 0;
@@ -7198,6 +7189,31 @@
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 {
:where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light] {
color-scheme: light;

1072
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

1072
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,
title: "Precision Engineering"
}, () =>
Div({ class: "space-y-4" }, [
P("SigPro-UI provides instant reactivity out of the box."),
Button({
div({ class: "space-y-4" }, [
p("SigPro-UI provides instant reactivity out of the box."),
button({
class: "btn-primary",
onclick: () => isVisible(false)
}, "Confirm")

View File

@@ -8,14 +8,14 @@ Collapsible accordion component for organizing content into expandable sections.
## Props
| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `title` | `string \| VNode \| Signal` | Required | Accordion section title |
| `open` | `boolean \| Signal<boolean>` | `false` | Whether the accordion is expanded |
| `name` | `string` | `auto-generated` | Group name for radio-style accordions |
| `class` | `string` | `''` | Additional CSS classes |
| `children` | `VNode \| Array<VNode>` | Required | Content to display when expanded |
| `items` | `Array` | `-` | Array of accordion items (alternative API) |
| Prop | Type | Default | Description |
| :--------- | :--------------------------- | :--------------- | :----------------------------------------- |
| `title` | `string \| VNode \| Signal` | Required | Accordion section title |
| `open` | `boolean \| Signal<boolean>` | `false` | Whether the accordion is expanded |
| `name` | `string` | `auto-generated` | Group name for radio-style accordions |
| `class` | `string` | `''` | Additional CSS classes |
| `children` | `VNode \| Array<VNode>` | Required | Content to display when expanded |
| `items` | `Array` | `-` | Array of accordion items (alternative API) |
## Live Examples
@@ -35,355 +35,34 @@ const BasicDemo = () => {
const open1 = $(false);
const open2 = $(false);
const open3 = $(false);
return Div({ class: 'flex flex-col gap-2' }, [
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: [
return div({ class: "flex flex-col gap-2" }, [
Accordion(
{
title: 'First Item',
open: () => openItems().item1,
children: Div({ class: 'p-2' }, 'This is the content of the first item.')
title: "Section 1",
open: open1,
},
{
title: 'Second Item',
open: () => openItems().item2,
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 =>
div(
{ class: "p-2" },
"Content for section 1. This is a basic accordion section.",
),
),
Accordion({
name: 'faq-group',
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']),
title: "Section 2",
open: open2,
children: Div({ class: 'p-2 space-y-2' }, [
Div({ class: 'flex items-center gap-3 p-2 hover:bg-base-100 rounded-lg' }, [
Div({ class: 'avatar placeholder' }, [
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' }, [
}, div(
{ class: "p-2" },
"Content for section 2. You can put any content here.",
),),
Accordion({
name: 'form-steps',
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']),
title: "Section 3",
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 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-success' }, 'Operation completed successfully!'),
Alert({ class: 'alert-warning' }, 'Please review your input before proceeding.'),
@@ -62,7 +62,7 @@ mount(BasicDemo, '#demo-basic');
const { Alert, Div, mount } = window;
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-solid' }, 'Solid info alert'),
Alert({ class: 'alert-success alert-soft' }, 'Soft success alert'),
@@ -104,14 +104,14 @@ const ActionsDemo = () => {
Toast(`Restored: ${deletedItem()}`, 'alert-success', 2000);
};
return Div({ class: 'flex flex-col gap-4' }, [
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 B') }, 'Delete Document B')
return div({ class: 'flex flex-col gap-4' }, [
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 B') }, 'Delete Document B')
]),
() => showUndo() ? Alert({ class: 'alert-warning alert-soft flex justify-between items-center' }, [
Span({}, `Deleted: ${deletedItem()}`),
Button({ class: 'btn btn-sm btn-primary', onclick: undoDelete }, 'Undo')
span({}, `Deleted: ${deletedItem()}`),
button({ class: 'btn btn-sm btn-primary', onclick: undoDelete }, 'Undo')
]) : null
]);
};
@@ -133,12 +133,12 @@ const { Alert, Button, Div, mount } = window;
const DismissibleDemo = () => {
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' }, [
Span({}, 'This alert can be dismissed. Click the X button to close.'),
Button({ class: 'btn btn-xs btn-circle btn-ghost', onclick: () => visible(false) }, '✕')
span({}, 'This alert can be dismissed. Click the X button to close.'),
button({ class: 'btn btn-xs btn-circle btn-ghost', onclick: () => visible(false) }, '✕')
]) : 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');
@@ -169,8 +169,8 @@ const ReactiveDemo = () => {
}
};
return Div({ class: 'flex flex-col gap-4' }, [
Input({
return div({ class: 'flex flex-col gap-4' }, [
input({
class: 'input input-bordered',
placeholder: 'Enter your email',
value: email,
@@ -196,7 +196,7 @@ mount(ReactiveDemo, '#demo-reactive');
const { Alert, Div, mount } = window;
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-success' }, '✅ This is a success alert'),
Alert({ class: 'alert-warning' }, '⚠️ This is a warning alert'),

View File

@@ -1,276 +1,60 @@
# 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-body">
<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>
```js
const { Autocomplete, mount } = window;
const paises = [
"España",
"México",
"Argentina",
"Colombia",
"Chile",
"Perú",
"Venezuela",
{ label: "Estados Unidos", value: "US" },
{ label: "Canadá", value: "CA" },
{ label: "Reino Unido", value: "UK" },
];
const BasicDemo = () => {
const selected = $("");
const fruits = [
"Apple",
"Banana",
"Orange",
"Grape",
"Strawberry",
"Mango",
"Pineapple",
"Watermelon",
const App = () => {
const password = $("");
// Lógica de validación sencilla
const requirements = [
{ label: "Mínimo 8 caracteres", check: () => password().length >= 8 },
{ label: "Incluye un número", check: () => /\d/.test(password()) },
{ label: "Símbolo especial", check: () => /[^A-Za-z0-9]/.test(password()) }
];
return Autocomplete({
items: fruits,
value: selected,
onselect: (value) => selected(value),
});
};
mount(BasicDemo, "#demo-basic");
```
### With Objects
<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-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" }, [
Autocomplete({
items: countries,
value: selectedLabel,
onselect: (item) => {
const selectedItem =
typeof item === "string"
? countries.find((c) => c.label === item)
: item;
selected(selectedItem?.value || "");
selectedLabel(selectedItem?.label || "");
},
}),
Div(
{ class: "alert alert-info mt-4" },
() => `Selected: ${selected()} - ${selectedLabel()}`,
),
return div({ class: "p-10 max-w-md" }, [
Input({
type: "password",
value: password,
class: "input-warning",
oninput: (e) => password(e.target.value),
label: "Pass",
float: true,
left: span({ class: "icon-[lucide--lock] mr-2" }),
// El contenido que se animará con fx() dentro del Input
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" },
requirements.map(req => h('li', {
class: () => `flex items-center text-sm ${req.check() ? 'text-success' : 'text-error opacity-50'}`
}, [
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");
```
### 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");
mount(App, "#app-demo");
```

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -139,9 +139,9 @@ mount(ActionsDemo, '#demo-actions');
```javascript
const UserDropdown = () => {
return Dropdown({
label: Span({ class: 'flex items-center gap-2' }, [
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')
label: span({ class: 'flex items-center gap-2' }, [
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')
]),
'John Doe'
]),
@@ -209,15 +209,15 @@ const NotificationsDropdown = () => {
};
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',
items: () => notifications().map(notif => ({
label: Div({ class: 'flex flex-col' }, [
Span({ class: 'font-medium' }, notif.title),
Span({ class: 'text-xs opacity-60' }, notif.time)
label: div({ class: 'flex flex-col' }, [
span({ class: 'font-medium' }, notif.title),
span({ class: 'text-xs opacity-60' }, notif.time)
]),
class: notif.read ? '' : 'bg-primary/5',
onclick: () => markAsRead(notif.id)
@@ -245,7 +245,7 @@ const VariantsDemo = () => {
{ 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: 'With Icon', icon: '☰', items: commonItems }),
Dropdown({ label: 'End Position', class: 'dropdown-end', items: commonItems })

View File

@@ -64,7 +64,7 @@ Fab({
```javascript
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({
icon: '',
actions: [
@@ -89,7 +89,7 @@ mount(BasicDemo, '#demo-basic');
```javascript
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({
label: 'Create',
icon: '✨',
@@ -117,9 +117,9 @@ mount(LabelDemo, '#demo-label');
const PositionsDemo = () => {
const position = $('bottom-6 right-6');
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' }, [
Select({
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' }, [
select({
items: [
{ value: 'bottom-6 right-6', label: 'Bottom Right' },
{ value: 'bottom-6 left-6', label: 'Bottom Left' },
@@ -130,7 +130,7 @@ const PositionsDemo = () => {
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({
@@ -171,9 +171,9 @@ const ColorsDemo = () => {
error: { class: 'btn-error', icon: '🔴' }
};
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' }, [
Select({
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' }, [
select({
items: Object.keys(variants).map(v => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) })),
value: variant,
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({
icon: () => count() > 0 ? `🔢 ${count()}` : '🎛️',
actions: actions
@@ -258,11 +258,11 @@ const DocumentActions = () => {
setTimeout(() => saved(false), 3000);
};
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: 'text-6xl mb-4' }, '📄'),
Div({ class: 'text-sm opacity-70' }, 'Untitled Document'),
() => saved() ? Div({ class: 'mt-4' }, Alert({ type: 'success', message: '✓ Saved successfully' })) : null
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: 'text-6xl mb-4' }, '📄'),
div({ class: 'text-sm opacity-70' }, 'Untitled Document'),
() => saved() ? div({ class: 'mt-4' }, Alert({ type: 'success', message: '✓ Saved successfully' })) : null
]),
Fab({
icon: '✏️',
@@ -291,11 +291,11 @@ mount(DocumentActions, '#demo-document');
const MessagingFAB = () => {
const unread = $(3);
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: 'text-6xl mb-4' }, '💬'),
Div({ class: 'text-sm opacity-70' }, 'Messages'),
() => unread() > 0 ? Div({ class: 'badge badge-error mt-2' }, `${unread()} unread`) : null
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: 'text-6xl mb-4' }, '💬'),
div({ class: 'text-sm opacity-70' }, 'Messages'),
() => unread() > 0 ? div({ class: 'badge badge-error mt-2' }, `${unread()} unread`) : null
]),
Fab({
icon: () => `💬${unread() > 0 ? ` ${unread()}` : ''}`,
@@ -353,22 +353,22 @@ const VariantsDemo = () => {
{ icon: '📅', label: 'Schedule', onclick: () => Toast('Scheduled', 'alert-info', 2000) }
];
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: 'relative border rounded-lg bg-base-200' }, [
Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Primary'),
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: 'relative border rounded-lg bg-base-200' }, [
span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Primary'),
Fab({ icon: '🔵', class: 'btn-primary', actions, position: 'bottom-6 left-6' })
]),
Div({ class: 'relative border rounded-lg bg-base-200' }, [
Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Secondary'),
div({ class: 'relative border rounded-lg bg-base-200' }, [
span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Secondary'),
Fab({ icon: '🟣', class: 'btn-secondary', actions, position: 'bottom-6 right-6' })
]),
Div({ class: 'relative border rounded-lg bg-base-200' }, [
Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Accent'),
div({ class: 'relative border rounded-lg bg-base-200' }, [
span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Accent'),
Fab({ icon: '🔴', class: 'btn-accent', actions, position: 'top-6 left-6' })
]),
Div({ class: 'relative border rounded-lg bg-base-200' }, [
Span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Success'),
div({ class: 'relative border rounded-lg bg-base-200' }, [
span({ class: 'absolute top-2 left-2 text-xs opacity-50' }, 'Success'),
Fab({ icon: '🟢', class: 'btn-success', actions, position: 'top-6 right-6' })
])
])

View File

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

View File

@@ -30,7 +30,7 @@ Indicator uses **daisyUI Indicator and Badge classes**:
```javascript
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
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' },
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' },
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' },
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
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' },
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: 'avatar placeholder' }, [
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' },
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: 'avatar placeholder' }, [
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' },
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: 'avatar placeholder' }, [
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 count = $(0);
return Div({ class: 'flex flex-col gap-4 items-center' }, [
return div({ class: 'flex flex-col gap-4 items-center' }, [
Indicator({
value: () => count() > 0 ? count() : null,
class: 'badge-primary'
},
Button({
button({
class: 'btn btn-lg btn-primary',
onclick: () => count(count() + 1)
}, 'Notifications')
),
Div({ class: 'flex gap-2' }, [
Button({
div({ class: 'flex gap-2' }, [
button({
class: 'btn btn-sm',
onclick: () => count(Math.max(0, count() - 1))
}, 'Decrease'),
Button({
button({
class: 'btn btn-sm btn-ghost',
onclick: () => count(0)
}, 'Clear')
@@ -161,24 +161,24 @@ const CartDemo = () => {
const total = () => cart().reduce((sum, item) => sum + item.price, 0);
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex justify-between items-center' }, [
return div({ class: 'flex flex-col gap-4' }, [
div({ class: 'flex justify-between items-center' }, [
Indicator({
value: () => cart().length,
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
? Div({ class: 'alert alert-soft text-center' }, 'Cart is empty')
: Div({ class: 'flex flex-col gap-2' }, cart().map(item =>
Div({ class: 'flex justify-between items-center p-2 bg-base-200 rounded-lg' }, [
Span({}, item.name),
Div({ class: 'flex gap-2 items-center' }, [
Span({ class: 'text-sm font-bold' }, `$${item.price}`),
Button({
? div({ class: 'alert alert-soft text-center' }, 'Cart is empty')
: div({ class: 'flex flex-col gap-2' }, cart().map(item =>
div({ class: 'flex justify-between items-center p-2 bg-base-200 rounded-lg' }, [
span({}, item.name),
div({ class: 'flex gap-2 items-center' }, [
span({ class: 'text-sm font-bold' }, `$${item.price}`),
button({
class: 'btn btn-xs btn-ghost btn-circle',
onclick: () => removeItem(item.id)
}, '✕')
@@ -219,15 +219,15 @@ const InboxDemo = () => {
}
};
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex justify-between items-center' }, [
return div({ class: 'flex flex-col gap-4' }, [
div({ class: 'flex justify-between items-center' }, [
Indicator({
value: () => unread(),
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',
onclick: () => {
messages().forEach(m => m.read = true);
@@ -236,14 +236,14 @@ const InboxDemo = () => {
}
}, 'Mark all read')
]),
Div({ class: 'flex flex-col gap-2' }, () => messages().map(msg =>
Div({
div({ class: 'flex flex-col gap-2' }, () => messages().map(msg =>
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'}`,
onclick: () => markAsRead(msg.id)
}, [
Div({ class: 'font-medium' }, msg.from),
Div({ class: 'text-sm' }, msg.subject),
!msg.read && Span({ class: 'badge badge-xs badge-primary mt-1' }, 'New')
div({ class: 'font-medium' }, msg.from),
div({ class: 'text-sm' }, msg.subject),
!msg.read && span({ class: 'badge badge-xs badge-primary mt-1' }, 'New')
])
))
]);
@@ -263,20 +263,20 @@ mount(InboxDemo, '#demo-inbox');
```javascript
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' },
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' },
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' },
Div({ class: 'avatar' }, [
Div({ class: 'w-10 h-10 rounded-full bg-primary' })
div({ class: 'avatar' }, [
div({ class: 'w-10 h-10 rounded-full bg-primary' })
])
),
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 name = $("");
return Input({
return input({
placeholder: "Enter your name",
value: name,
oninput: (e) => name(e.target.value)
@@ -68,7 +68,7 @@ const { InputLabel, Div, Icon, mount } = window;
const IconDemo = () => {
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("✉️"),
h("input", {
class: "grow",
@@ -97,7 +97,7 @@ const { Input, Div, Icon, Swap, mount } = window;
const PasswordDemo = () => {
const password = $("");
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]"),
h("input", {
type: () => (visible() ? "text" : "password"),
@@ -133,9 +133,9 @@ const { Input, Div, Span, mount } = window;
const LabelDemo = () => {
const email = $("");
return Div({ class: "floating-label" }, [
Span("Email"),
Input({
return div({ class: "floating-label" }, [
span("Email"),
input({
type: "email",
value: email,
placeholder: " ",
@@ -163,7 +163,7 @@ const { Input, Tooltip, mount } = window;
const TooltipDemo = () => {
const username = $("");
return Tooltip({ tip: "Must be at least 3 characters" }, [
Input({
input({
placeholder: "Username",
value: username,
oninput: (e) => username(e.target.value)
@@ -190,7 +190,7 @@ const { Input, Div, mount } = window;
const ErrorDemo = () => {
const email = $("");
const isValid = () => email().includes("@");
return Div({ class: "flex flex-col gap-2" }, [
return div({ class: "flex flex-col gap-2" }, [
h("input", {
type: "email",
class: () => `input input-bordered ${email() && !isValid() ? "input-error" : ""}`,
@@ -198,7 +198,7 @@ const ErrorDemo = () => {
placeholder: "mail@example.com",
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");
@@ -217,7 +217,7 @@ mount(ErrorDemo, "#demo-error");
const { Input, mount } = window;
const DisabledDemo = () => {
return Input({ value: "john.doe", disabled: true });
return input({ value: "john.doe", disabled: true });
};
mount(DisabledDemo, "#demo-disabled");
```
@@ -236,18 +236,18 @@ const { Input, Div, mount } = window;
const VariantsDemo = () => {
const text = $("");
return Div({ class: "flex flex-col gap-4" }, [
Input({ placeholder: "Default", value: text, oninput: (e) => text(e.target.value) }),
Input({ class: "input-primary", placeholder: "Primary", value: $("") }),
Input({ class: "input-secondary", placeholder: "Secondary", value: $("") }),
Input({ class: "input-accent", placeholder: "Accent", value: $("") }),
Input({ class: "input-ghost", placeholder: "Ghost", value: $("") }),
Input({ class: "input-info", placeholder: "Info", value: $("") }),
Input({ class: "input-success", placeholder: "Success", value: $("") }),
Input({ class: "input-warning", placeholder: "Warning", value: $("") }),
Input({ class: "input-error", placeholder: "Error", value: $("") }),
Input({ type: "number", placeholder: "Number", value: $(0), oninput: (e) => e.target.value }),
Input({ type: "date", value: $("2024-01-01") })
return div({ class: "flex flex-col gap-4" }, [
input({ placeholder: "Default", value: text, oninput: (e) => text(e.target.value) }),
input({ class: "input-primary", placeholder: "Primary", value: $("") }),
input({ class: "input-secondary", placeholder: "Secondary", value: $("") }),
input({ class: "input-accent", placeholder: "Accent", value: $("") }),
input({ class: "input-ghost", placeholder: "Ghost", value: $("") }),
input({ class: "input-info", placeholder: "Info", value: $("") }),
input({ class: "input-success", placeholder: "Success", value: $("") }),
input({ class: "input-warning", placeholder: "Warning", value: $("") }),
input({ class: "input-error", placeholder: "Error", value: $("") }),
input({ type: "number", placeholder: "Number", value: $(0), oninput: (e) => e.target.value }),
input({ type: "date", value: $("2024-01-01") })
]);
};
mount(VariantsDemo, "#demo-variants");

View File

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

View File

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

View File

@@ -42,8 +42,8 @@ Modal supports all **daisyUI Modal classes**:
const BasicDemo = () => {
const isOpen = $(false);
return Div({ class: 'flex justify-center' }, [
Button({
return div({ class: 'flex justify-center' }, [
button({
class: 'btn btn-primary',
onclick: () => {
isOpen(true);
@@ -52,14 +52,14 @@ const BasicDemo = () => {
Modal({
open: isOpen,
title: 'Basic Modal',
buttons: Button({
buttons: button({
class: 'btn-primary',
onclick: () => {
isOpen(false);
}
}, '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);
};
return Div({ class: 'flex flex-col gap-4 items-center' }, [
Button({
return div({ class: 'flex flex-col gap-4 items-center' }, [
button({
class: 'btn btn-primary',
onclick: () => isOpen(true)
}, 'Confirm Action'),
@@ -116,17 +116,17 @@ const ActionsDemo = () => {
open: isOpen,
title: 'Confirm Action',
buttons: [
Button({
button({
class: 'btn btn-ghost',
onclick: () => isOpen(false)
}, 'Cancel'),
Button({
button({
class: 'btn btn-primary',
onclick: handleConfirm
}, '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' }, [
Button({
return div({ class: 'flex flex-col gap-4 items-center' }, [
button({
class: 'btn btn-primary',
onclick: () => isOpen(true)
}, 'Sign Up'),
@@ -171,24 +171,24 @@ const FormModal = () => {
open: isOpen,
title: 'Create Account',
buttons: [
Button({
button({
class: 'btn btn-ghost',
onclick: () => isOpen(false)
}, 'Cancel'),
Button({
button({
class: 'btn btn-primary',
onclick: handleSubmit
}, 'Sign Up')
]
}, [
Div({ class: 'flex flex-col gap-4 py-2' }, [
Input({
div({ class: 'flex flex-col gap-4 py-2' }, [
input({
label: 'Full Name',
value: name,
placeholder: 'Enter your name',
oninput: (e) => name(e.target.value)
}),
Input({
input({
label: 'Email',
type: 'email',
value: email,
@@ -232,11 +232,11 @@ const ConfirmDemo = () => {
Toast(`Deleted: ${pendingDelete().name}`, 'alert-info', 2000);
};
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex flex-col gap-2' }, items().map(item =>
Div({ class: 'flex justify-between items-center p-3 bg-base-200 rounded-lg' }, [
Span({}, item.name),
Button({
return div({ class: 'flex flex-col gap-4' }, [
div({ class: 'flex flex-col gap-2' }, items().map(item =>
div({ class: 'flex justify-between items-center p-3 bg-base-200 rounded-lg' }, [
span({}, item.name),
button({
class: 'btn btn-xs btn-error',
onclick: () => confirmDelete(item)
}, 'Delete')
@@ -246,17 +246,17 @@ const ConfirmDemo = () => {
open: isOpen,
title: 'Delete Confirmation',
buttons: [
Button({
button({
class: 'btn btn-ghost',
onclick: () => isOpen(false)
}, 'Cancel'),
Button({
button({
class: 'btn btn-error',
onclick: handleDelete
}, '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 isOpen = $(false);
return Div({ class: 'flex justify-center' }, [
Button({
return div({ class: 'flex justify-center' }, [
button({
class: 'btn btn-primary',
onclick: () => isOpen(true)
}, 'Open Large Modal'),
Modal({
open: isOpen,
title: 'Terms and Conditions',
buttons: Button({
buttons: button({
class: 'btn btn-primary',
onclick: () => isOpen(false)
}, 'I Agree')
}, [
Div({ class: 'py-4 max-h-96 overflow-y-auto' }, [
Div({ class: 'space-y-4' }, [
Div({ class: 'text-sm' }, [
Div({ class: 'font-bold mb-2' }, '1. Introduction'),
div({ class: 'py-4 max-h-96 overflow-y-auto' }, [
div({ class: 'space-y-4' }, [
div({ class: 'text-sm' }, [
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.'
]),
Div({ class: 'text-sm' }, [
Div({ class: 'font-bold mb-2' }, '2. User Obligations'),
div({ class: 'text-sm' }, [
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.'
]),
Div({ class: 'text-sm' }, [
Div({ class: 'font-bold mb-2' }, '3. Privacy Policy'),
div({ class: 'text-sm' }, [
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.'
]),
Div({ class: 'text-sm' }, [
Div({ class: 'font-bold mb-2' }, '4. Termination'),
div({ class: 'text-sm' }, [
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.'
])
])
@@ -330,27 +330,27 @@ const MultipleDemo = () => {
const modal2 = $(false);
const modal3 = $(false);
return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [
Button({ class: 'btn', onclick: () => modal1(true) }, 'Info Modal'),
Button({ class: 'btn', onclick: () => modal2(true) }, 'Success Modal'),
Button({ class: 'btn', onclick: () => modal3(true) }, 'Warning Modal'),
return div({ class: 'flex flex-wrap gap-4 justify-center' }, [
button({ class: 'btn', onclick: () => modal1(true) }, 'Info Modal'),
button({ class: 'btn', onclick: () => modal2(true) }, 'Success Modal'),
button({ class: 'btn', onclick: () => modal3(true) }, 'Warning Modal'),
Modal({
open: modal1,
title: 'Information',
buttons: Button({ onclick: () => modal1(false) }, 'OK')
buttons: button({ onclick: () => modal1(false) }, 'OK')
}, 'This is an informational message.'),
Modal({
open: modal2,
title: 'Success!',
buttons: Button({ onclick: () => modal2(false) }, 'Great!')
buttons: button({ onclick: () => modal2(false) }, 'Great!')
}, 'Your operation was completed successfully.'),
Modal({
open: modal3,
title: 'Warning',
buttons: Button({ onclick: () => modal3(false) }, 'Understood')
buttons: button({ onclick: () => modal3(false) }, 'Understood')
}, 'Please review your input before proceeding.')
]);
};
@@ -370,8 +370,8 @@ mount(MultipleDemo, '#demo-multiple');
const CustomDemo = () => {
const isOpen = $(false);
return Div({ class: 'flex justify-center' }, [
Button({
return div({ class: 'flex justify-center' }, [
button({
class: 'btn btn-primary',
onclick: () => isOpen(true)
}, 'Open Custom Modal'),
@@ -379,11 +379,11 @@ const CustomDemo = () => {
open: isOpen,
class: 'bg-gradient-to-r from-primary to-secondary text-primary-content'
}, [
Div({ class: 'text-center py-8' }, [
Div({ class: 'text-6xl mb-4' }, '🎉'),
Div({ class: 'text-2xl font-bold mb-2' }, 'Congratulations!'),
Div({ class: 'mb-6' }, 'You\'ve successfully completed the tutorial.'),
Button({
div({ class: 'text-center py-8' }, [
div({ class: 'text-6xl mb-4' }, '🎉'),
div({ class: 'text-2xl font-bold mb-2' }, 'Congratulations!'),
div({ class: 'mb-6' }, 'You\'ve successfully completed the tutorial.'),
button({
class: 'btn btn-ghost bg-white/20 hover:bg-white/30',
onclick: () => isOpen(false)
}, 'Get Started')

View File

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

View File

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

View File

@@ -46,7 +46,7 @@ Range supports all **daisyUI Range classes**:
const BasicDemo = () => {
const value = $(50);
return Div({ class: 'flex flex-col gap-4' }, [
return div({ class: 'flex flex-col gap-4' }, [
Range({
label: 'Volume',
value: value,
@@ -54,7 +54,7 @@ const BasicDemo = () => {
max: 100,
oninput: (e) => value(parseInt(e.target.value))
}),
Div({ class: 'text-center' }, () => `Value: ${value()}%`)
div({ class: 'text-center' }, () => `Value: ${value()}%`)
]);
};
mount(BasicDemo, '#demo-basic');
@@ -73,7 +73,7 @@ mount(BasicDemo, '#demo-basic');
const TooltipDemo = () => {
const brightness = $(75);
return Div({ class: 'flex flex-col gap-4' }, [
return div({ class: 'flex flex-col gap-4' }, [
Range({
label: 'Brightness',
value: brightness,
@@ -82,7 +82,7 @@ const TooltipDemo = () => {
tooltip: () => `${brightness()}% brightness`,
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');
@@ -103,7 +103,7 @@ const ColorsDemo = () => {
const secondary = $(60);
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: '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) })
@@ -128,7 +128,7 @@ const SizesDemo = () => {
const md = $(75);
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: '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) }),
@@ -152,7 +152,7 @@ const PriceDemo = () => {
const price = $(500);
const maxPrice = 1000;
return Div({ class: 'flex flex-col gap-4' }, [
return div({ class: 'flex flex-col gap-4' }, [
Range({
label: 'Price Range',
value: price,
@@ -161,12 +161,12 @@ const PriceDemo = () => {
step: 10,
oninput: (e) => price(parseInt(e.target.value))
}),
Div({ class: 'flex justify-between' }, [
Span({}, '$0'),
Span({}, () => `$${price()}`),
Span({}, `$${maxPrice}`)
div({ class: 'flex justify-between' }, [
span({}, '$0'),
span({}, () => `$${price()}`),
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() < 750) return 'Mid range';
return 'Premium';
@@ -191,9 +191,9 @@ const AudioDemo = () => {
const bass = $(40);
const treble = $(60);
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex items-center gap-3' }, [
Span({ class: 'w-12' }, '🔊'),
return div({ class: 'flex flex-col gap-4' }, [
div({ class: 'flex items-center gap-3' }, [
span({ class: 'w-12' }, '🔊'),
Range({
value: volume,
min: 0,
@@ -201,10 +201,10 @@ const AudioDemo = () => {
class: 'range-primary flex-1',
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' }, [
Span({ class: 'w-12' }, '🎵 Bass'),
div({ class: 'flex items-center gap-3' }, [
span({ class: 'w-12' }, '🎵 Bass'),
Range({
value: bass,
min: 0,
@@ -212,10 +212,10 @@ const AudioDemo = () => {
class: 'range-secondary flex-1',
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' }, [
Span({ class: 'w-12' }, '🎶 Treble'),
div({ class: 'flex items-center gap-3' }, [
span({ class: 'w-12' }, '🎶 Treble'),
Range({
value: treble,
min: 0,
@@ -223,7 +223,7 @@ const AudioDemo = () => {
class: 'range-accent flex-1',
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 value = $(50);
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-sm font-bold' }, 'With Label'),
return div({ class: 'flex flex-col gap-4' }, [
div({ class: 'text-sm font-bold' }, 'With Label'),
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) => {} }),
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) => {} })
]);
};

View File

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

View File

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

View File

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

View File

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

View File

@@ -111,8 +111,8 @@ const CustomDemo = () => {
return Swap({
value: isOn,
on: Div({ class: "badge badge-success gap-1" }, ["✅", " Active"]),
off: Div({ class: "badge badge-ghost gap-1" }, ["⭕", " Inactive"])
on: div({ class: "badge badge-success gap-1" }, ["✅", " Active"]),
off: div({ class: "badge badge-ghost gap-1" }, ["⭕", " Inactive"])
});
};
mount(CustomDemo, '#demo-custom');
@@ -131,16 +131,16 @@ mount(CustomDemo, '#demo-custom');
const ReactiveDemo = () => {
const isOn = $(false);
return Div({ class: 'flex flex-col gap-4 items-center' }, [
return div({ class: 'flex flex-col gap-4 items-center' }, [
Swap({
value: isOn,
on: "👁️",
off: "👁️‍🗨️"
}),
Div({ class: 'text-center' }, () =>
div({ class: 'text-center' }, () =>
isOn()
? Div({ class: 'alert alert-success' }, 'Content is visible')
: Div({ class: 'alert alert-soft' }, 'Content is hidden')
? div({ class: 'alert alert-success' }, 'Content is visible')
: div({ class: 'alert alert-soft' }, 'Content is hidden')
)
]);
};
@@ -162,33 +162,33 @@ const ModeDemo = () => {
const notifications = $(true);
const sound = $(false);
return Div({ class: 'flex flex-col gap-4 w-full' }, [
Div({ class: 'flex justify-between items-center' }, [
Span({}, 'Dark mode'),
return div({ class: 'flex flex-col gap-4 w-full' }, [
div({ class: 'flex justify-between items-center' }, [
span({}, 'Dark mode'),
Swap({
value: darkMode,
on: "🌙",
off: "☀️"
})
]),
Div({ class: 'flex justify-between items-center' }, [
Span({}, 'Notifications'),
div({ class: 'flex justify-between items-center' }, [
span({}, 'Notifications'),
Swap({
value: notifications,
on: "🔔",
off: "🔕"
})
]),
Div({ class: 'flex justify-between items-center' }, [
Span({}, 'Sound effects'),
div({ class: 'flex justify-between items-center' }, [
span({}, 'Sound effects'),
Swap({
value: sound,
on: "🔊",
off: "🔇"
})
]),
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: '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'}`)
])
]);
};
@@ -206,33 +206,33 @@ mount(ModeDemo, '#demo-mode');
```javascript
const VariantsDemo = () => {
return Div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [
Div({ class: 'text-center' }, [
Div({ class: 'text-xs mb-2' }, 'Volume'),
return div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [
div({ class: 'text-center' }, [
div({ class: 'text-xs mb-2' }, 'Volume'),
Swap({
value: $(false),
on: "🔊",
off: "🔇"
})
]),
Div({ class: 'text-center' }, [
Div({ class: 'text-xs mb-2' }, 'Like'),
div({ class: 'text-center' }, [
div({ class: 'text-xs mb-2' }, 'Like'),
Swap({
value: $(true),
on: "❤️",
off: "🤍"
})
]),
Div({ class: 'text-center' }, [
Div({ class: 'text-xs mb-2' }, 'Star'),
div({ class: 'text-center' }, [
div({ class: 'text-xs mb-2' }, 'Star'),
Swap({
value: $(false),
on: "⭐",
off: "☆"
})
]),
Div({ class: 'text-center' }, [
Div({ class: 'text-xs mb-2' }, 'Check'),
div({ class: 'text-center' }, [
div({ class: 'text-xs mb-2' }, 'Check'),
Swap({
value: $(true),
on: "✅",
@@ -261,11 +261,11 @@ const TodoDemo = () => {
{ id: 3, text: 'Deploy to production', completed: $(false) }
];
return Div({ class: 'flex flex-col gap-3' }, [
Div({ class: 'text-sm font-bold mb-2' }, 'Todo list'),
return div({ class: 'flex flex-col gap-3' }, [
div({ class: 'text-sm font-bold mb-2' }, 'Todo list'),
...todos.map(todo =>
Div({ class: 'flex items-center justify-between p-2 bg-base-200 rounded-lg' }, [
Span({ class: todo.completed() ? 'line-through opacity-50' : '' }, todo.text),
div({ class: 'flex items-center justify-between p-2 bg-base-200 rounded-lg' }, [
span({ class: todo.completed() ? 'line-through opacity-50' : '' }, todo.text),
Swap({
value: todo.completed,
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;
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' }
];
return Table({
return table({
items: users,
columns: [
{ label: 'ID', key: 'id' },
@@ -91,7 +91,7 @@ const ZebraDemo = () => {
{ id: 4, name: 'Monitor', price: '$299', stock: 12 }
];
return Table({
return table({
items: products,
columns: [
{ label: 'Product', key: 'name' },
@@ -121,7 +121,7 @@ const CustomDemo = () => {
{ id: 103, customer: 'Charlie', amount: 450, status: 'shipped' }
];
return Table({
return table({
items: orders,
columns: [
{ label: 'Order ID', key: 'id' },
@@ -140,7 +140,7 @@ const CustomDemo = () => {
pending: 'badge badge-warning',
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 totalExpenses = sales.reduce((sum, item) => sum + item.expenses, 0);
return Table({
return table({
items: sales,
columns: [
{ label: 'Month', key: 'month' },
@@ -211,15 +211,15 @@ mount(FooterDemo, '#demo-footer');
const EmptyDemo = () => {
const emptyList = [];
return Table({
return table({
items: emptyList,
columns: [
{ label: 'ID', key: 'id' },
{ label: 'Name', key: 'name' }
],
empty: Div({ class: 'flex flex-col items-center gap-2 p-4' }, [
Span({ class: 'text-2xl' }, '📭'),
Span({}, 'No records found')
empty: div({ class: 'flex flex-col items-center gap-2 p-4' }, [
span({ class: 'text-2xl' }, '📭'),
span({}, 'No records found')
])
});
};
@@ -259,26 +259,26 @@ const ReactiveDemo = () => {
tasks([...tasks(), { id: newId, title: `Task ${newId}`, completed: false }]);
};
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'flex gap-2' }, [
Button({
return div({ class: 'flex flex-col gap-4' }, [
div({ class: 'flex gap-2' }, [
button({
class: 'btn btn-sm',
onclick: () => filter('all')
}, 'All'),
Button({
button({
class: 'btn btn-sm',
onclick: () => filter('completed')
}, 'Completed'),
Button({
button({
class: 'btn btn-sm',
onclick: () => filter('pending')
}, 'Pending'),
Button({
button({
class: 'btn btn-sm btn-primary',
onclick: addTask
}, 'Add Task')
]),
Table({
table({
items: filteredTasks,
columns: [
{ label: 'ID', key: 'id' },
@@ -286,8 +286,8 @@ const ReactiveDemo = () => {
{
label: 'Status',
render: (item) => item.completed
? Span({ class: 'badge badge-success' }, '✓ Done')
: Span({ class: 'badge badge-warning' }, '○ Pending')
? span({ class: 'badge badge-success' }, '✓ Done')
: span({ class: 'badge badge-warning' }, '○ Pending')
}
],
zebra: true
@@ -325,7 +325,7 @@ const ActionsDemo = () => {
));
};
return Table({
return table({
items: users,
columns: [
{ label: 'ID', key: 'id' },
@@ -334,17 +334,17 @@ const ActionsDemo = () => {
{
label: 'Status',
render: (item) => item.active
? Span({ class: 'badge badge-success' }, 'Active')
: Span({ class: 'badge badge-ghost' }, 'Inactive')
? span({ class: 'badge badge-success' }, 'Active')
: span({ class: 'badge badge-ghost' }, 'Inactive')
},
{
label: 'Actions',
render: (item) => Div({ class: 'flex gap-1' }, [
Button({
render: (item) => div({ class: 'flex gap-1' }, [
button({
class: 'btn btn-xs btn-ghost',
onclick: () => toggleActive(item.id)
}, item.active ? 'Deactivate' : 'Activate'),
Button({
button({
class: 'btn btn-xs btn-error',
onclick: () => deleteUser(item.id)
}, 'Delete')
@@ -374,9 +374,9 @@ const VariantsDemo = () => {
{ id: 3, name: 'Item 3', value: 300 }
];
return Div({ class: 'flex flex-col gap-6' }, [
Div({ class: 'text-sm font-bold' }, 'Default Table'),
Table({
return div({ class: 'flex flex-col gap-6' }, [
div({ class: 'text-sm font-bold' }, 'Default Table'),
table({
items: data,
columns: [
{ label: 'ID', key: 'id' },
@@ -385,8 +385,8 @@ const VariantsDemo = () => {
]
}),
Div({ class: 'text-sm font-bold mt-4' }, 'Zebra Stripes'),
Table({
div({ class: 'text-sm font-bold mt-4' }, 'Zebra Stripes'),
table({
items: data,
columns: [
{ label: 'ID', key: 'id' },
@@ -396,8 +396,8 @@ const VariantsDemo = () => {
zebra: true
}),
Div({ class: 'text-sm font-bold mt-4' }, 'Compact Table'),
Table({
div({ class: 'text-sm font-bold mt-4' }, 'Compact Table'),
table({
items: data,
columns: [
{ label: 'ID', key: 'id' },

View File

@@ -70,19 +70,19 @@ const BasicDemo = () => {
label: 'Tab 1',
active: () => 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',
active: () => 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',
active: () => 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({
items: [
{
label: Span({ class: 'flex items-center gap-2' }, ['🏠', 'Home']),
label: span({ class: 'flex items-center gap-2' }, ['🏠', 'Home']),
active: () => 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',
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',
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',
active: () => activeTab() === 'profile',
onclick: () => activeTab('profile'),
content: Div({ class: 'p-4' }, 'Profile information here.')
content: div({ class: 'p-4' }, 'Profile information here.')
},
{
label: 'Settings',
tip: 'Adjust your preferences',
active: () => activeTab() === 'settings',
onclick: () => activeTab('settings'),
content: Div({ class: 'p-4' }, 'Settings configuration.')
content: div({ class: 'p-4' }, 'Settings configuration.')
},
{
label: 'Notifications',
tip: 'Manage notifications',
active: () => 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',
active: () => activeTab() === 'basic',
onclick: () => activeTab('basic'),
content: Div({ class: 'p-4' }, 'Basic features available.')
content: div({ class: 'p-4' }, 'Basic features available.')
},
{
label: 'Premium',
disabled: true,
tip: 'Upgrade to access',
content: Div({ class: 'p-4' }, 'Premium content (locked)')
content: div({ class: 'p-4' }, 'Premium content (locked)')
},
{
label: 'Pro',
disabled: true,
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',
active: () => activeTab() === 'counter',
onclick: () => activeTab('counter'),
content: Div({ class: 'p-4 text-center' }, [
Div({ class: 'text-4xl font-bold mb-4' }, () => count()),
Button({
content: div({ class: 'p-4 text-center' }, [
div({ class: 'text-4xl font-bold mb-4' }, () => count()),
button({
class: 'btn btn-primary',
onclick: () => count(count() + 1)
}, 'Increment')
@@ -242,13 +242,13 @@ const ReactiveDemo = () => {
label: 'Timer',
active: () => 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',
active: () => 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());
};
return Div({ class: 'flex flex-col gap-4' }, [
return div({ class: 'flex flex-col gap-4' }, [
Tabs({
items: [
{
label: 'Personal Info',
active: () => activeTab() === 'personal',
onclick: () => activeTab('personal'),
content: Div({ class: 'p-4 space-y-4' }, [
Input({
content: div({ class: 'p-4 space-y-4' }, [
input({
label: 'Name',
value: () => formData().name,
placeholder: 'Enter your name',
oninput: (e) => updateField('name', e.target.value)
}),
Input({
input({
label: 'Email',
type: 'email',
value: () => formData().email,
@@ -313,14 +313,14 @@ const FormTabs = () => {
label: 'Address',
active: () => activeTab() === 'address',
onclick: () => activeTab('address'),
content: Div({ class: 'p-4 space-y-4' }, [
Input({
content: div({ class: 'p-4 space-y-4' }, [
input({
label: 'Address',
value: () => formData().address,
placeholder: 'Street address',
oninput: (e) => updateField('address', e.target.value)
}),
Input({
input({
label: 'City',
value: () => formData().city,
placeholder: 'City',
@@ -332,7 +332,7 @@ const FormTabs = () => {
label: 'Preferences',
active: () => activeTab() === 'prefs',
onclick: () => activeTab('prefs'),
content: Div({ class: 'p-4 space-y-4' }, [
content: div({ class: 'p-4 space-y-4' }, [
Checkbox({
label: 'Email notifications',
value: () => formData().notifications,
@@ -347,8 +347,8 @@ const FormTabs = () => {
}
]
}),
Div({ class: 'flex justify-end mt-4' }, [
Button({
div({ class: 'flex justify-end mt-4' }, [
button({
class: 'btn btn-primary',
onclick: handleSubmit
}, 'Submit')
@@ -379,39 +379,39 @@ const VariantsDemo = () => {
label: 'Tab 1',
active: () => active() === 'tab1',
onclick: () => active('tab1'),
content: Div({ class: 'p-4' }, 'Content 1')
content: div({ class: 'p-4' }, 'Content 1')
},
{
label: 'Tab 2',
active: () => active() === 'tab2',
onclick: () => active('tab2'),
content: Div({ class: 'p-4' }, 'Content 2')
content: div({ class: 'p-4' }, 'Content 2')
},
{
label: 'Tab 3',
active: () => active() === 'tab3',
onclick: () => active('tab3'),
content: Div({ class: 'p-4' }, 'Content 3')
content: div({ class: 'p-4' }, 'Content 3')
},
{
label: 'Tab 4',
active: () => 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' }, [
Div({ class: 'text-sm font-bold' }, 'Default Tabs'),
return div({ class: 'flex flex-col gap-6' }, [
div({ class: 'text-sm font-bold' }, 'Default Tabs'),
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' }),
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' }),
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' })
]);
};
@@ -427,9 +427,9 @@ let nextTabId = 4;
const ClosableTabsDemo = () => {
const tabs = $([
{ 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 3', content: Div('Content 3'), closable: 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 3', content: div('Content 3'), closable: true }
]);
// Opcional: si quieres que la primera pestaña esté activa al inicio,
@@ -440,14 +440,14 @@ const ClosableTabsDemo = () => {
const newId = nextTabId++;
tabs([...tabs(), {
label: `Tab ${newId}`,
content: Div(`Content ${newId}`),
content: div(`Content ${newId}`),
onClose: (item) => console.log('Closing Individual', item),
closable: true
}]);
};
return Div({ class: 'flex flex-col gap-4' }, [
Button({ class: 'btn btn-sm btn-outline mb-2', onclick: addTab }, 'Add Tab'),
return div({ class: 'flex flex-col gap-4' }, [
button({ class: 'btn btn-sm btn-outline mb-2', onclick: addTab }, 'Add Tab'),
Tabs({ items: tabs, onTabClose: (item) => console.log('Closing', item) })
]);
};

View File

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

View File

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

View File

@@ -29,7 +29,7 @@ Tooltip supports all **daisyUI Tooltip classes**:
```javascript
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
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' }, [
Button({ class: 'btn btn-primary' }, 'Hover me')
button({ class: 'btn btn-primary' }, 'Hover me')
]),
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' }, [
Span({ class: 'text-2xl' }, '')
span({ class: 'text-2xl' }, '')
])
]);
};
@@ -72,18 +72,18 @@ mount(BasicDemo, '#demo-basic');
```javascript
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' }, [
Button({ class: 'btn btn-sm' }, 'Top')
button({ class: 'btn btn-sm' }, 'Top')
]),
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' }, [
Button({ class: 'btn btn-sm' }, 'Left')
button({ class: 'btn btn-sm' }, 'Left')
]),
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
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' }, [
Button({ class: 'btn btn-ghost btn-circle' }, '💾')
button({ class: 'btn btn-ghost btn-circle' }, '💾')
]),
Tooltip({ tip: 'Edit item' }, [
Button({ class: 'btn btn-ghost btn-circle' }, '✏️')
button({ class: 'btn btn-ghost btn-circle' }, '✏️')
]),
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' }, [
Button({ class: 'btn btn-ghost btn-circle' }, '⚙️')
button({ class: 'btn btn-ghost btn-circle' }, '⚙️')
])
]);
};
@@ -133,20 +133,20 @@ const FormDemo = () => {
const username = $('');
const email = $('');
return Div({ class: 'flex flex-col gap-4 max-w-md mx-auto' }, [
Div({ class: 'flex items-center gap-2' }, [
Input({
return div({ class: 'flex flex-col gap-4 max-w-md mx-auto' }, [
div({ class: 'flex items-center gap-2' }, [
input({
label: 'Username',
value: username,
placeholder: 'Choose a username',
oninput: (e) => username(e.target.value)
}),
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' }, [
Input({
div({ class: 'flex items-center gap-2' }, [
input({
label: 'Email',
type: 'email',
value: email,
@@ -154,7 +154,7 @@ const FormDemo = () => {
oninput: (e) => email(e.target.value)
}),
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);
};
return Div({ class: 'flex flex-col gap-4 items-center' }, [
return div({ class: 'flex flex-col gap-4 items-center' }, [
Tooltip({ tip: () => tooltipText() }, [
Button({
button({
class: 'btn btn-primary btn-lg',
onclick: () => Toast('Button clicked!', 'alert-info', 2000)
}, 'Interactive Button')
]),
Div({ class: 'flex gap-2 flex-wrap justify-center mt-4' }, [
Button({
div({ class: 'flex gap-2 flex-wrap justify-center mt-4' }, [
button({
class: 'btn btn-xs',
onclick: () => updateTooltip('You clicked the button!')
}, 'Change Tooltip'),
Button({
button({
class: 'btn btn-xs',
onclick: () => updateTooltip('Try hovering now!')
}, 'Change Again')
@@ -215,28 +215,28 @@ mount(InteractiveDemo, '#demo-interactive');
```javascript
const RichDemo = () => {
return Div({ class: 'flex flex-wrap gap-4 justify-center' }, [
return div({ class: 'flex flex-wrap gap-4 justify-center' }, [
Tooltip({
tip: Div({ class: 'text-left p-1' }, [
Div({ class: 'font-bold' }, 'User Info'),
Div({ class: 'text-xs' }, 'John Doe'),
Div({ class: 'text-xs' }, 'john@example.com'),
Div({ class: 'badge badge-xs badge-primary mt-1' }, 'Admin')
tip: div({ class: 'text-left p-1' }, [
div({ class: 'font-bold' }, 'User Info'),
div({ class: 'text-xs' }, 'John Doe'),
div({ class: 'text-xs' }, 'john@example.com'),
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({
tip: Div({ class: 'text-left p-1' }, [
Div({ class: 'font-bold flex items-center gap-1' }, [
Span({}, '⚠️'),
Span({}, 'System Status')
tip: div({ class: 'text-left p-1' }, [
div({ class: 'font-bold flex items-center gap-1' }, [
span({}, '⚠️'),
span({}, 'System Status')
]),
Div({ class: 'text-xs' }, 'All systems operational'),
Div({ class: 'text-xs text-success' }, '✓ 99.9% uptime')
div({ class: 'text-xs' }, 'All systems operational'),
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
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' }, [
Button({ class: 'btn btn-primary btn-sm' }, 'Primary')
button({ class: 'btn btn-primary btn-sm' }, 'Primary')
]),
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' }, [
Button({ class: 'btn btn-accent btn-sm' }, 'Accent')
button({ class: 'btn btn-accent btn-sm' }, 'Accent')
]),
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' }, [
Button({ class: 'btn btn-success btn-sm' }, 'Success')
button({ class: 'btn btn-success btn-sm' }, 'Success')
]),
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' }, [
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
const AllPositionsDemo = () => {
return Div({ class: 'grid grid-cols-3 gap-4 justify-items-center' }, [
Div({ class: 'col-start-2' }, [
return div({ class: 'grid grid-cols-3 gap-4 justify-items-center' }, [
div({ class: 'col-start-2' }, [
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' }, [
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' }, [
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' }, [
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' }, [
h('h1', { class: 'text-2xl font-bold mb-4' }, 'SigProUI Demo'),
Input({
input({
placeholder: 'Enter your name...'
}),
Button({
button({
class: 'btn-primary mt-4',
onclick: () => count(count() + 1)
}, () => `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' }, [
h('h1', { class: 'text-2xl font-bold mb-4' }, 'SigProUI Demo'),
Input({
input({
value: name,
placeholder: 'Enter your name...'
}),
Button({
button({
class: 'btn-primary mt-4',
onclick: () => count(count() + 1)
}, () => `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/#/)
### UI Components
- `Button()` - Styled button with DaisyUI
- `Input()` - Form input with floating labels
- `button()` - Styled button with DaisyUI
- `input()` - Form input with floating labels
- `Alert()` - Alert messages
- `Modal()` - Modal dialogs
- `Table()` - Data tables
@@ -147,8 +147,8 @@ import { tt, Locale } from 'sigpro-ui';
Locale('en');
// Use translations
const closeButton = Button({}, tt('close')());
const searchPlaceholder = Input({ placeholder: tt('search')() });
const closeButton = button({}, tt('close')());
const searchPlaceholder = input({ placeholder: tt('search')() });
```
## TypeScript Support
@@ -159,7 +159,7 @@ SigProUI includes TypeScript definitions. Import types as needed:
import { Button, Input, type ButtonProps, type InputProps } from 'sigpro-ui';
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 |
| :--- | :--- | :--- |
| **Button** | Styled button with DaisyUI | `Button({ class: "btn-primary" }, "Submit")` |
| **Input** | Reactive text field with validation | `Input({ value: $name, validate: (v) => !v ? "Required" : "" })` |
| **Button** | Styled button with DaisyUI | `button({ class: "btn-primary" }, "Submit")` |
| **Input** | Reactive text field with validation | `input({ value: $name, validate: (v) => !v ? "Required" : "" })` |
| **Select** | Dropdown selection menu | `Select({ options: ["Admin", "User"], value: $role })` |
| **Checkbox** | Binary toggle (boolean) | `Checkbox({ label: "Active", checked: $isActive })` |
| **Table** | Data grid with column rendering | `Table({ items: $data, columns: [...] })` |
@@ -37,9 +37,9 @@ import "sigpro-ui/css";
| 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 })` |
| **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 })` |
| **Colorpicker** | Visual color picker with palette | `Colorpicker({ label: "Theme", value: $color })` |
| **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
const email = $('');
Input({
input({
type: 'email',
value: email,
placeholder: 'Enter your email',
@@ -90,7 +90,7 @@ Input({
| **Stat** | Statistical data blocks (KPIs) | `Stat({ label: "Total", value: "1.2k", desc: "Monthly" })` |
| **Timeline** | Vertical/horizontal timeline | `Timeline({ items: [{ title: "Step 1", detail: "Completed" }] })` |
| **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!")` |
| **Modal** | Dialog overlay | `Modal({ open: $isOpen, title: "Confirm" }, "Are you sure?")` |
| **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 }] })` |
| **Accordion** | Collapsible sections | `Accordion({ title: "Details" }, "Hidden content")` |
| **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 |
| :--- | :--- | :--- |
| **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.
```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.
@@ -166,7 +166,7 @@ const closeText = tt("close"); // "Close" or "Cerrar"
```javascript
const name = $("");
Input({
input({
value: name,
placeholder: "Name",
validate: (value) => {
@@ -203,7 +203,7 @@ Modal({
open: showModal,
title: "Delete Item",
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?");
```

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

View File

@@ -1,15 +1,15 @@
import * as AccordionModule from './components/accordion.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 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 CarouselModule from './components/carousel.js';
import * as ChatModule from './components/chat.js';
import * as CheckboxModule from './components/checkbox.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 DropdownModule from './components/dropdown.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 IconModule from './components/icon.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 ListModule from './components/List.js';
import * as LoadingModule from './components/loading.js';

View File

@@ -60,74 +60,38 @@
font-size: 14px;
}
.input,
.label,
.select,
.textarea {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:focus,
&:focus-within {
outline: 1px solid transparent !important;
outline-offset: 1px !important;
outline: none !important;
box-shadow: 0 0 4px 0px;
}
&:hover:not(:focus) {
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 {
color: oklch(30% 0.01 260); /* Gris más oscuro (30% es más oscuro que 45%) */
font-size: 1.1rem; /* text-base: más grande que 0.875rem */
color: oklch(30% 0.01 260);
font-size: 1.1rem;
transition: all 0.2s ease;
}
.floating-label:focus-within span {
color: oklch(25% 0.02 260); /* Aún más oscuro al enfocar */
font-size: 1.1rem; /* Mantiene el mismo tamaño */
color: oklch(25% 0.02 260);
font-size: 1.1rem;
}
.floating-label:has(input:not(:placeholder-shown)) span {
color: oklch(28% 0.01 260); /* Gris oscuro cuando tiene valor */
font-size: 1.1rem; /* Mantiene el mismo tamaño */
color: oklch(28% 0.01 260);
font-size: 1.1rem;
}
.tab-content-inner {
@@ -135,6 +99,16 @@
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 {
from {
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 {
button {
@apply btn;

View File

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

View File

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

View File

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

View File

@@ -53,7 +53,7 @@ export const Modal = (props, children) => {
h("div", { class: "modal-action" }, [
h("form", { method: "dialog", class: "flex gap-2" }, [
...(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]),
Button({
button({
class: "btn-xs btn-circle btn-ghost",
onclick: close
}, closeIcon)