minusculas
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 4s

This commit is contained in:
2026-04-22 08:27:59 +02:00
parent 65d78ca215
commit 5a5f593025
63 changed files with 610 additions and 748 deletions

View File

@@ -12,21 +12,10 @@ Collapsible accordion component for organizing content into expandable sections.
| :--- | :--- | :--- | :--- |
| `title` | `string \| VNode \| Signal` | Required | Accordion section title |
| `open` | `boolean \| Signal<boolean>` | `false` | Whether the accordion is expanded |
| `name` | `string` | `-` | Group name for radio-style accordions (only one open at a time) |
| `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) |
| `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 |
## Styling
Accordion supports all **daisyUI Collapse classes**:
| Category | Keywords | Description |
| :--- | :--- | :--- |
| Type | `collapse-arrow`, `collapse-plus`, `collapse-minus` | Expand indicator style |
| Color | `collapse-primary`, `collapse-secondary`, `collapse-accent` | Color variants |
| Background | `bg-base-100`, `bg-base-200` | Background colors |
> For further details, check the [daisyUI Collapse Documentation](https://daisyui.com/components/collapse) Full reference for CSS classes.
| `items` | `Array` | `-` | Array of accordion items (alternative API) |
## Live Examples
@@ -39,7 +28,9 @@ Accordion supports all **daisyUI Collapse classes**:
</div>
</div>
```javascript
```js
const { Accordion, Div, Mount } = window;
const BasicDemo = () => {
const open1 = $(false);
const open2 = $(false);
@@ -49,24 +40,18 @@ const BasicDemo = () => {
Accordion({
title: 'Section 1',
open: open1,
onclick: () => open1(!open1())
}, [
Div({ class: 'p-2' }, 'Content for section 1. This is a basic accordion section.')
]),
children: Div({ class: 'p-2' }, 'Content for section 1. This is a basic accordion section.')
}),
Accordion({
title: 'Section 2',
open: open2,
onclick: () => open2(!open2())
}, [
Div({ class: 'p-2' }, 'Content for section 2. You can put any content here.')
]),
children: Div({ class: 'p-2' }, 'Content for section 2. You can put any content here.')
}),
Accordion({
title: 'Section 3',
open: open3,
onclick: () => open3(!open3())
}, [
Div({ class: 'p-2' }, 'Content for section 3. Accordions are great for FAQs.')
])
children: Div({ class: 'p-2' }, 'Content for section 3. Accordions are great for FAQs.')
})
]);
};
Mount(BasicDemo, '#demo-basic');
@@ -81,40 +66,78 @@ Mount(BasicDemo, '#demo-basic');
</div>
</div>
```javascript
```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',
name: 'group',
open: () => openSection() === 'section1',
onclick: () => openSection('section1')
}, [
Div({ class: 'p-2' }, 'Content for section 1. Only one section can be open at a time.')
]),
children: Div({ class: 'p-2' }, 'Content for section 1. Only one section can be open at a time.')
}),
Accordion({
name: 'group',
title: 'Section 2',
name: 'group',
open: () => openSection() === 'section2',
onclick: () => openSection('section2')
}, [
Div({ class: 'p-2' }, 'Content for section 2. Opening this will close section 1.')
]),
children: Div({ class: 'p-2' }, 'Content for section 2. Opening this will close section 1.')
}),
Accordion({
title: 'Section 3',
name: 'group',
title: 'Section 3',
open: () => openSection() === 'section3',
onclick: () => openSection('section3')
}, [
Div({ class: 'p-2' }, 'Content for section 3. This is useful for FAQ sections.')
])
children: Div({ class: 'p-2' }, 'Content for section 3. This is useful for FAQ sections.')
})
]);
};
Mount(GroupDemo, '#demo-group');
```
### Using Items Array
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
<div class="card-body">
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
<div id="demo-items" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```js
const { Accordion, Div, Mount } = window;
const ItemsDemo = () => {
const openItems = $({
item1: true,
item2: false,
item3: false
});
return Accordion({
items: [
{
title: 'First Item',
open: () => openItems().item1,
children: Div({ class: 'p-2' }, 'This is the content of the first item.')
},
{
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">
@@ -124,26 +147,25 @@ Mount(GroupDemo, '#demo-group');
</div>
</div>
```javascript
```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. Use the open prop to control expansion.' },
{ id: 'faq3', question: 'Can I have multiple open?', answer: 'Yes! By default, accordions can be opened independently. Use the name prop to create groups where only one can be open.' },
{ id: 'faq4', question: 'Is it accessible?', answer: 'Yes, the accordion uses proper ARIA attributes and keyboard navigation support.' }
{ id: 'faq2', question: 'How do I use it?', answer: 'Simply import the Accordion component and pass title and children props.' },
{ id: 'faq3', question: 'Can I have multiple open?', answer: 'Yes! By default, accordions can be opened independently.' }
];
return Div({ class: 'flex flex-col gap-2' }, faqs.map(faq =>
Accordion({
title: faq.question,
name: 'faq-group',
title: faq.question,
open: () => openFaq() === faq.id,
onclick: () => openFaq(openFaq() === faq.id ? '' : faq.id)
}, [
Div({ class: 'p-2 text-sm' }, faq.answer)
])
children: Div({ class: 'p-2 text-sm' }, faq.answer)
})
));
};
Mount(FaqDemo, '#demo-faq');
@@ -158,7 +180,9 @@ Mount(FaqDemo, '#demo-faq');
</div>
</div>
```javascript
```js
const { Accordion, Div, Span, Mount } = window;
const RichDemo = () => {
const open1 = $(true);
const open2 = $(false);
@@ -167,9 +191,7 @@ const RichDemo = () => {
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['📊', 'Statistics']),
open: open1,
onclick: () => open1(!open1())
}, [
Div({ class: 'p-2' }, [
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'),
@@ -178,24 +200,14 @@ const RichDemo = () => {
Div({ class: 'stat bg-base-100 rounded-lg p-3' }, [
Div({ class: 'stat-title' }, 'Revenue'),
Div({ class: 'stat-value text-lg' }, '$45,678')
]),
Div({ class: 'stat bg-base-100 rounded-lg p-3' }, [
Div({ class: 'stat-title' }, 'Growth'),
Div({ class: 'stat-value text-lg text-success' }, '+23%')
]),
Div({ class: 'stat bg-base-100 rounded-lg p-3' }, [
Div({ class: 'stat-title' }, 'Active'),
Div({ class: 'stat-value text-lg' }, '89%')
])
])
])
]),
}),
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['👥', 'Team Members']),
open: open2,
onclick: () => open2(!open2())
}, [
Div({ class: 'p-2 space-y-2' }, [
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')
@@ -204,18 +216,9 @@ const RichDemo = () => {
Div({ class: 'font-medium' }, 'John Doe'),
Div({ class: 'text-sm opacity-70' }, 'Developer')
])
]),
Div({ class: 'flex items-center gap-3 p-2 hover:bg-base-100 rounded-lg' }, [
Div({ class: 'avatar placeholder' }, [
Div({ class: 'bg-secondary text-secondary-content rounded-full w-10 h-10 flex items-center justify-center' }, 'JS')
]),
Div({ class: 'flex-1' }, [
Div({ class: 'font-medium' }, 'Jane Smith'),
Div({ class: 'text-sm opacity-70' }, 'Designer')
])
])
])
])
})
]);
};
Mount(RichDemo, '#demo-rich');
@@ -230,7 +233,9 @@ Mount(RichDemo, '#demo-rich');
</div>
</div>
```javascript
```js
const { Accordion, Div, Span, Button, Input, Radio, Mount } = window;
const FormAccordion = () => {
const openStep = $('step1');
const formData = $({
@@ -255,18 +260,15 @@ const FormAccordion = () => {
};
const handleSubmit = () => {
Toast('Form submitted!', 'alert-success', 2000);
console.log(formData());
window.Toast('Form submitted!', 'alert-success', 2000);
};
return Div({ class: 'flex flex-col gap-2' }, [
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['1⃣', 'Personal Information']),
name: 'form-steps',
title: Span({ class: 'flex items-center gap-2' }, ['1⃣', 'Personal Information']),
open: () => openStep() === 'step1',
onclick: () => openStep('step1')
}, [
Div({ class: 'p-4 space-y-4' }, [
children: Div({ class: 'p-4 space-y-4' }, [
Input({
label: 'Full Name',
value: () => formData().name,
@@ -288,14 +290,12 @@ const FormAccordion = () => {
}, 'Next →')
])
])
]),
}),
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['2⃣', 'Address']),
name: 'form-steps',
title: Span({ class: 'flex items-center gap-2' }, ['2⃣', 'Address']),
open: () => openStep() === 'step2',
onclick: () => openStep('step2')
}, [
Div({ class: 'p-4 space-y-4' }, [
children: Div({ class: 'p-4 space-y-4' }, [
Input({
label: 'Address',
value: () => formData().address,
@@ -304,20 +304,15 @@ const FormAccordion = () => {
}),
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 →')
Button({ class: 'btn btn-primary btn-sm', onclick: nextStep }, 'Next →')
])
])
]),
}),
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['3⃣', 'Payment']),
name: 'form-steps',
title: Span({ class: 'flex items-center gap-2' }, ['3⃣', 'Payment']),
open: () => openStep() === 'step3',
onclick: () => openStep('step3')
}, [
Div({ class: 'p-4 space-y-4' }, [
children: Div({ class: 'p-4 space-y-4' }, [
Div({ class: 'flex flex-col gap-2' }, [
Radio({
label: 'Credit Card',
@@ -343,7 +338,7 @@ const FormAccordion = () => {
Button({ class: 'btn btn-success btn-sm', onclick: handleSubmit }, 'Submit')
])
])
])
})
]);
};
Mount(FormAccordion, '#demo-form');
@@ -354,11 +349,13 @@ Mount(FormAccordion, '#demo-form');
<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 flex flex-col gap-6"></div>
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Accordion, Div, Span, Mount } = window;
const VariantsDemo = () => {
const open1 = $(true);
const open2 = $(false);
@@ -366,34 +363,26 @@ const VariantsDemo = () => {
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-sm font-bold' }, 'Default Accordion'),
Div({ class: 'flex flex-col gap-2' }, [
Accordion({ title: 'Default style', open: open1, onclick: () => open1(!open1()) }, [
Div({ class: 'p-2' }, 'Default accordion with standard styling.')
])
]),
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'),
Div({ class: 'flex flex-col gap-2' }, [
Accordion({
title: Span({ class: 'text-primary font-bold' }, 'Primary Title'),
open: open2,
onclick: () => open2(!open2()),
class: 'bg-primary/5 border-primary/20'
}, [
Div({ class: 'p-2' }, 'Accordion with custom styling and primary color.')
])
]),
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'),
Div({ class: 'flex flex-col gap-2' }, [
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['✨', 'Featured Content']),
open: open3,
onclick: () => open3(!open3())
}, [
Div({ class: 'p-2' }, 'Accordion with emoji icons in the title.')
])
])
Accordion({
title: Span({ class: 'flex items-center gap-2' }, ['✨', 'Featured Content']),
open: open3,
children: Div({ class: 'p-2' }, 'Accordion with emoji icons in the title.')
})
]);
};
Mount(VariantsDemo, '#demo-variants');

View File

@@ -10,36 +10,20 @@ Alert component for displaying contextual messages, notifications, and feedback
| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `type` | `string` | `'info'` | Alert type: `'info'`, `'success'`, `'warning'`, `'error'` |
| `soft` | `boolean \| Signal<boolean>` | `true` | Use soft variant (subtle background) |
| `actions` | `VNode \| function` | `-` | Optional action buttons or content |
| `message` | `string \| VNode \| Signal` | `-` | Alert message content |
| `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) |
| `children` | `string \| VNode` | `-` | Alert content (alternative to `message`) |
| `children` | `string \| VNode \| Array<VNode>` | Required | Alert content |
## Styling
Alert supports all **daisyUI Alert classes**:
| Category | Keywords | Description |
| Category | Classes | Description |
| :--- | :--- | :--- |
| Color | `alert-info`, `alert-success`, `alert-warning`, `alert-error` | Alert type variants |
| Style | `alert-soft` (default), `alert-solid` | Visual style variants |
> For further details, check the [daisyUI Alert Documentation](https://daisyui.com/components/alert) Full reference for CSS classes.
### Example
```javascript
Alert({
type: "success",
soft: false,
class: "shadow-lg",
message: "Operation completed!"
});
// Applies: solid success alert with shadow
```
## Live Examples
### Basic Alerts
@@ -47,17 +31,19 @@ Alert({
<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 flex flex-col gap-3"></div>
<div id="demo-basic" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Alert, Div, Mount } = window;
const BasicDemo = () => {
return Div({ class: 'flex flex-col gap-3' }, [
Alert({ type: 'info', message: 'This is an informational message.' }),
Alert({ type: 'success', message: 'Operation completed successfully!' }),
Alert({ type: 'warning', message: 'Please review your input before proceeding.' }),
Alert({ type: 'error', message: 'An error occurred while processing your request.' })
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.'),
Alert({ class: 'alert-error' }, 'An error occurred while processing your request.')
]);
};
Mount(BasicDemo, '#demo-basic');
@@ -68,17 +54,19 @@ Mount(BasicDemo, '#demo-basic');
<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 flex flex-col gap-3"></div>
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Alert, Div, Mount } = window;
const VariantsDemo = () => {
return Div({ class: 'flex flex-col gap-3' }, [
Alert({ type: 'info', soft: true, message: 'Soft info alert (default)' }),
Alert({ type: 'info', soft: false, message: 'Solid info alert' }),
Alert({ type: 'success', soft: true, message: 'Soft success alert' }),
Alert({ type: 'success', soft: false, message: 'Solid success alert' })
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'),
Alert({ class: 'alert-success alert-solid' }, 'Solid success alert')
]);
};
Mount(VariantsDemo, '#demo-variants');
@@ -89,11 +77,13 @@ Mount(VariantsDemo, '#demo-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-actions" class="bg-base-100 p-6 rounded-xl border border-base-300 flex flex-col gap-3"></div>
<div id="demo-actions" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Alert, Button, Div, Mount, Toast } = window;
const ActionsDemo = () => {
const showUndo = $(false);
const deletedItem = $(null);
@@ -119,15 +109,10 @@ const ActionsDemo = () => {
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({
type: 'warning',
soft: true,
message: `Deleted: ${deletedItem()}`,
actions: Button({
class: 'btn btn-sm btn-primary',
onclick: undoDelete
}, 'Undo')
}) : null
() => 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')
]) : null
]);
};
Mount(ActionsDemo, '#demo-actions');
@@ -138,27 +123,22 @@ Mount(ActionsDemo, '#demo-actions');
<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-dismissible" class="bg-base-100 p-6 rounded-xl border border-base-300 flex flex-col gap-3"></div>
<div id="demo-dismissible" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Alert, Button, Div, Mount } = window;
const DismissibleDemo = () => {
const visible = $(true);
return Div({ class: 'flex flex-col gap-3' }, [
() => visible() ? Alert({
type: 'info',
message: 'This alert can be dismissed. Click the X button to close.',
actions: 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() ? 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) }, '✕')
]) : null,
() => !visible() ? Button({ class: 'btn btn-sm btn-ghost', onclick: () => visible(true) }, 'Show Alert') : null
]);
};
Mount(DismissibleDemo, '#demo-dismissible');
@@ -173,7 +153,9 @@ Mount(DismissibleDemo, '#demo-dismissible');
</div>
</div>
```javascript
```js
const { Alert, Div, Input, Mount } = window;
const ReactiveDemo = () => {
const email = $('');
const error = $('');
@@ -189,126 +171,37 @@ const ReactiveDemo = () => {
return Div({ class: 'flex flex-col gap-4' }, [
Input({
label: 'Email Address',
class: 'input input-bordered',
placeholder: 'Enter your email',
value: email,
oninput: (e) => validateEmail(e.target.value)
}),
() => error() ? Alert({ type: 'error', message: error() }) : null,
() => email() && !error() ? Alert({
type: 'success',
message: `Valid email: ${email()}`
}) : null
() => error() ? Alert({ class: 'alert-error' }, error()) : null,
() => email() && !error() ? Alert({ class: 'alert-success' }, `Valid email: ${email()}`) : null
]);
};
Mount(ReactiveDemo, '#demo-reactive');
```
### Form Validation
<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>
```javascript
const FormDemo = () => {
const name = $('');
const email = $('');
const submitted = $(false);
const errors = $({ name: '', email: '' });
const validate = () => {
const newErrors = {
name: name().trim() ? '' : 'Name is required',
email: email().trim() ? (email().includes('@') ? '' : 'Invalid email') : 'Email is required'
};
errors(newErrors);
return !newErrors.name && !newErrors.email;
};
const handleSubmit = () => {
if (validate()) {
submitted(true);
setTimeout(() => submitted(false), 3000);
Toast('Form submitted successfully!', 'alert-success', 2000);
}
};
return Div({ class: 'flex flex-col gap-4' }, [
Div({ class: 'text-lg font-bold' }, 'Contact Form'),
Input({
label: 'Name',
value: name,
error: () => errors().name,
oninput: (e) => {
name(e.target.value);
validate();
}
}),
Input({
label: 'Email',
value: email,
error: () => errors().email,
oninput: (e) => {
email(e.target.value);
validate();
}
}),
Button({ class: 'btn btn-primary', onclick: handleSubmit }, 'Submit'),
() => submitted() ? Alert({
type: 'success',
message: 'Thank you! We will contact you soon.'
}) : null,
() => (errors().name || errors().email) ? Alert({
type: 'error',
message: 'Please fix the errors above before submitting.'
}) : null
]);
};
Mount(FormDemo, '#demo-form');
```
### Icon Alerts
<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-icons" class="bg-base-100 p-6 rounded-xl border border-base-300 flex flex-col gap-3"></div>
</div>
</div>
```javascript
const IconsDemo = () => {
return Div({ class: 'flex flex-col gap-3' }, [
Alert({ type: 'info', message: 'Information alert with custom icon' }),
Alert({ type: 'success', message: 'Success alert with custom icon' }),
Alert({ type: 'warning', message: 'Warning alert with custom icon' }),
Alert({ type: 'error', message: 'Error alert with custom icon' })
]);
};
Mount(IconsDemo, '#demo-icons');
```
### All Types
<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-all" class="bg-base-100 p-6 rounded-xl border border-base-300 flex flex-col gap-3"></div>
<div id="demo-all" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Alert, Div, Mount } = window;
const AllTypesDemo = () => {
return Div({ class: 'flex flex-col gap-3' }, [
Alert({ type: 'info', message: ' This is an info alert' }),
Alert({ type: 'success', message: '✅ This is a success alert' }),
Alert({ type: 'warning', message: '⚠️ This is a warning alert' }),
Alert({ type: 'error', message: '❌ This is an error alert' })
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'),
Alert({ class: 'alert-error' }, '❌ This is an error alert')
]);
};
Mount(AllTypesDemo, '#demo-all');
```
```

View File

@@ -8,24 +8,24 @@ Searchable dropdown with autocomplete functionality, keyboard navigation, and re
## 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` | `'Search...'` | Placeholder text |
| 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 |
| 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.
@@ -36,22 +36,33 @@ Autocomplete wraps a **daisyUI Input component** internally. All Input styling c
<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 flex items-center justify-center"></div>
<div id="demo-basic" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Autocomplete, Mount } = window;
const BasicDemo = () => {
const selected = $('');
const fruits = ['Apple', 'Banana', 'Orange', 'Grape', 'Strawberry', 'Mango', 'Pineapple', 'Watermelon'];
const selected = $("");
const fruits = [
"Apple",
"Banana",
"Orange",
"Grape",
"Strawberry",
"Mango",
"Pineapple",
"Watermelon",
];
return Autocomplete({
items: fruits,
value: selected,
onselect: (value) => selected(value)
onselect: (value) => selected(value),
});
};
Mount(BasicDemo, '#demo-basic');
Mount(BasicDemo, "#demo-basic");
```
### With Objects
@@ -59,42 +70,46 @@ Mount(BasicDemo, '#demo-basic');
<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 flex flex-col gap-4"></div>
<div id="demo-objects" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Autocomplete, Div, Mount } = window;
const ObjectsDemo = () => {
const selected = $('');
const selectedLabel = $('');
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' }
{ value: "mx", label: "Mexico" },
{ value: "us", label: "United States" },
{ value: "ca", label: "Canada" },
{ value: "br", label: "Brazil" },
{ value: "ar", label: "Argentina" },
{ value: "es", label: "Spain" },
];
return Div({ class: 'flex flex-col gap-4 w-full' }, [
return Div({ class: "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 || '');
}
const selectedItem =
typeof item === "string"
? countries.find((c) => c.label === item)
: item;
selected(selectedItem?.value || "");
selectedLabel(selectedItem?.label || "");
},
}),
Div({ class: 'alert alert-success' }, [
() => `Selected: ${selected()} - ${selectedLabel()}`
])
Div(
{ class: "alert alert-info mt-4" },
() => `Selected: ${selected()} - ${selectedLabel()}`,
),
]);
};
Mount(ObjectsDemo, '#demo-objects');
Mount(ObjectsDemo, "#demo-objects");
```
### With Reactive Display
@@ -102,30 +117,45 @@ Mount(ObjectsDemo, '#demo-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-reactive" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
<div id="demo-reactive" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Autocomplete, Div, Mount } = window;
const ReactiveDemo = () => {
const selected = $('');
const selected = $("");
const programmingLanguages = [
'JavaScript', 'Python', 'Java', 'C++', 'Ruby', 'Go', 'Rust', 'TypeScript', 'Swift', 'Kotlin'
"JavaScript",
"Python",
"Java",
"C++",
"Ruby",
"Go",
"Rust",
"TypeScript",
"Swift",
"Kotlin",
];
return Div({ class: 'flex flex-col gap-4 w-full' }, [
return Div({ class: "flex flex-col gap-4 w-full" }, [
Autocomplete({
items: programmingLanguages,
value: selected,
onselect: (value) => selected(value)
onselect: (value) => selected(value),
}),
() => selected() ? Div({ class: 'alert alert-info' }, [
`You selected: ${selected()}`
]) : null
() =>
selected()
? Div(
{ class: "alert alert-success mt-4" },
`You selected: ${selected()}`,
)
: null,
]);
};
Mount(ReactiveDemo, '#demo-reactive');
Mount(ReactiveDemo, "#demo-reactive");
```
### Dynamic Items
@@ -133,45 +163,63 @@ Mount(ReactiveDemo, '#demo-reactive');
<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 flex items-center justify-center"></div>
<div id="demo-dynamic" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Autocomplete, Select, SelectItems, Div, Mount } = window;
const DynamicDemo = () => {
const selected = $('');
const filterType = $('all');
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']
fruits: ["Apple", "Banana", "Orange", "Mango"],
vegetables: ["Carrot", "Broccoli", "Spinach", "Potato"],
all: [
"Apple",
"Banana",
"Orange",
"Mango",
"Carrot",
"Broccoli",
"Spinach",
"Potato",
],
};
return Div({ class: 'flex flex-col gap-4 w-full' }, [
Select({
class: 'select-bordered w-full',
value: filterType,
onchange: (e) => filterType(e.target.value)
}, [
Options({
items: [
{ value: 'all', label: 'All items' },
{ value: 'fruits', label: 'Fruits' },
{ value: 'vegetables', label: 'Vegetables' }
]
})
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),
}),
]),
Autocomplete({
items: () => allItems[filterType()],
value: selected,
onselect: (value) => selected(value)
})
]);
};
Mount(DynamicDemo, '#demo-dynamic');
Mount(DynamicDemo, "#demo-dynamic");
```
### All Variants
@@ -179,40 +227,50 @@ Mount(DynamicDemo, '#demo-dynamic');
<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 flex flex-col gap-4"></div>
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```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({}, [
Autocomplete({
class: 'input-primary',
items: colors,
value: $(''),
placeholder: 'Search colors...'
})
]),
Div({}, [
Autocomplete({
class: 'input-secondary',
items: colors,
value: $(''),
placeholder: 'Search colors...'
})
]),
Div({}, [
Autocomplete({
class: 'input-ghost',
items: colors,
value: $(''),
placeholder: 'Search colors...'
})
])
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(VariantsDemo, "#demo-variants");
```

View File

@@ -1,6 +1,6 @@
# Input
Form input component with icons, password toggle, and validation. Use `Label()` and `Tooltip()` as wrappers for label and tooltip functionality.
Form input component with icons, password toggle, and validation.
## Tag
@@ -13,11 +13,9 @@ Form input component with icons, password toggle, and validation. Use `Label()`
| `type` | `string` | `'text'` | Input type (text, password, email, number, date) |
| `value` | `string \| Signal<string>` | `''` | Input value |
| `placeholder` | `string` | `' '` | Placeholder text |
| `icon` | `string \| VNode \| Signal` | `-` | Icon displayed inside input |
| `disabled` | `boolean \| Signal<boolean>` | `false` | Disabled state |
| `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) |
| `oninput` | `function` | `-` | Input event handler |
| `validate` | `function` | `-` | Validation function returning error message |
## Styling
@@ -36,18 +34,19 @@ Input supports all **daisyUI Input classes**:
<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 flex items-center justify-center"></div>
<div id="demo-basic" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Input, Mount } = window;
const BasicDemo = () => {
const name = $("");
return Input({
placeholder: "Enter your name",
value: name,
oninput: (e) => name(e.target.value),
oninput: (e) => name(e.target.value)
});
};
Mount(BasicDemo, "#demo-basic");
@@ -55,25 +54,29 @@ Mount(BasicDemo, "#demo-basic");
### With Icon
Wrap the input inside a `Div` with class `input` and add an icon as a sibling.
<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-icon" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
<div id="demo-icon" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { InputLabel, Div, Icon, Mount } = window;
const IconDemo = () => {
const email = $("");
return Label({ class: "input" }, [
return Div({ class: "input input-bordered flex items-center gap-2" }, [
Icon("✉️"),
Input({
class: "grow",
Tag("input", {
class: "grow",
type: "email",
value: email,
oninput: (e) => email(e.target.value),
}),
placeholder: "Email",
oninput: (e) => email(e.target.value)
})
]);
};
Mount(IconDemo, "#demo-icon");
@@ -84,30 +87,31 @@ Mount(IconDemo, "#demo-icon");
<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-password" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
<div id="demo-password" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Input, Div, Icon, Swap, Mount } = window;
const PasswordDemo = () => {
const password = $("");
const visible = $(false);
return Label({ class: "input input-bordered w-full max-w-xs" }, [
return Div({ class: "input input-bordered flex items-center gap-2" }, [
Icon("icon-[lucide--lock]"),
Input({
Tag("input", {
type: () => (visible() ? "text" : "password"),
value: password,
placeholder: "Contraseña",
placeholder: "Password",
class: "grow",
oninput: (e) => password(e.target.value),
oninput: (e) => password(e.target.value)
}),
Swap({
value: visible,
class: "swap-rotate",
on: Icon("icon-[lucide--eye]"),
off: Icon("icon-[lucide--eye-off]"),
}),
off: Icon("icon-[lucide--eye-off]")
})
]);
};
Mount(PasswordDemo, "#demo-password");
@@ -115,93 +119,86 @@ Mount(PasswordDemo, "#demo-password");
### With Floating Label
Wrap the input with `Label()` component:
Use a wrapper `Div` with class `floating-label`.
<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-label" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
<div id="demo-label" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Input, Div, Span, Mount } = window;
const LabelDemo = () => {
const email = $("");
return Label({ class: "floating-label" }, [
Span("Text floating"),
return Div({ class: "floating-label" }, [
Span("Email"),
Input({
type: "email",
label: "Email",
value: email,
placeholder: "Clic here",
oninput: (e) => email(e.target.value),
}),
placeholder: " ",
oninput: (e) => email(e.target.value)
})
]);
};
Mount(LabelDemo, "#demo-label");
```
### With Tooltip & label
### With Tooltip
Wrap the input with `Tooltip()` component:
Wrap the input with `Tooltip` component.
<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-tooltip" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
<div id="demo-tooltip" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Input, Tooltip, Mount } = window;
const TooltipDemo = () => {
const username = $("");
return Tooltip(
{ tip: "Must be at least 3 characters" },
Label({ class: "input" }, [
Span({ class: "label" }, "User"),
Input({
value: username,
label: "Username",
placeholder: "Username",
oninput: (e) => username(e.target.value),
}),
]),
);
return Tooltip({ tip: "Must be at least 3 characters" }, [
Input({
placeholder: "Username",
value: username,
oninput: (e) => username(e.target.value)
})
]);
};
Mount(TooltipDemo, "#demo-tooltip");
```
### Error State
Add `input-error` class and show a validation message.
<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-error" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
<div id="demo-error" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Input, Div, Mount } = window;
const ErrorDemo = () => {
const email = $("");
return Div({ class: "form-control w-full max-w-xs" }, [
Label({ class: "label" }, Span({ class: "label-text" }, "Email")),
Div({ class: "relative w-full" }, [
Input({
type: "email",
value: email,
placeholder: "mail@site.com",
class: "input input-bordered w-full pl-10 validator",
required: true,
oninput: (e) => email(e.target.value)
}),
Span({ class: "absolute left-3 top-1/2 -translate-y-1/2 text-base-content/60" },
Icon("icon-[lucide--mail]")
)
]),
Div({ class: "validator-hint hidden" }, "Enter a valid email address")
const isValid = () => email().includes("@");
return Div({ class: "flex flex-col gap-2" }, [
Tag("input", {
type: "email",
class: () => `input input-bordered ${email() && !isValid() ? "input-error" : ""}`,
value: email,
placeholder: "mail@example.com",
oninput: (e) => email(e.target.value)
}),
() => email() && !isValid() ? Div({ class: "text-error text-sm" }, "Enter a valid email") : null
]);
};
Mount(ErrorDemo, "#demo-error");
@@ -212,16 +209,15 @@ Mount(ErrorDemo, "#demo-error");
<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-disabled" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
<div id="demo-disabled" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Input, Mount } = window;
const DisabledDemo = () => {
return Input({
value: "john.doe",
disabled: true,
});
return Input({ value: "john.doe", disabled: true });
};
Mount(DisabledDemo, "#demo-disabled");
```
@@ -231,38 +227,27 @@ Mount(DisabledDemo, "#demo-disabled");
<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 flex flex-col gap-4"></div>
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
</div>
</div>
```javascript
```js
const { Input, Div, Mount } = window;
const VariantsDemo = () => {
const text = $("");
const number = $(0);
return Div({ class: "flex flex-col gap-4" }, [
Input({
placeholder: "Type something...",
value: text,
oninput: (e) => text(e.target.value),
}),
Input({
type: "number",
value: number,
oninput: (e) => number(parseInt(e.target.value) || 0),
}),
Input({
type: "date",
value: $("2024-01-01"),
}),
Input({ class: "input-primary", value: "Primary" }),
Input({ class: "input-secondary", value: "Secondary" }),
Input({ class: "input-accent", value: "Accent" }),
Input({ class: "input-ghost", value: "Ghost" }),
Input({ class: "input-info", value: "Info" }),
Input({ class: "input-success", value: "Success" }),
Input({ class: "input-warning", value: "Warning" }),
Input({ class: "input-error", value: "Error" }),
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

@@ -41,17 +41,24 @@
plugins: [
function (hook, vm) {
hook.doneEach(function () {
// Buscamos los bloques de código JS que queremos ejecutar
// Seleccionamos solo los bloques marcados con ```js
const codeBlocks = document.querySelectorAll(
'pre[data-lang="javascript"] code',
'pre[data-lang="js"] code',
);
codeBlocks.forEach((code) => {
try {
const runDemo = new Function(code.innerText);
// Usamos un bloque anónimo para evitar colisiones de variables const/let
// si el usuario ejecuta el mismo código varias veces.
const scriptContent = `(function() {
${code.innerText}
})();`;
const runDemo = new Function(scriptContent);
runDemo();
} catch (err) {
console.error("Error en la demo de SigPro:", err);
// Un error común es que el bloque de código esté vacío o mal formado
console.error("Error ejecutando demo de SigPro:", err);
}
});
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long