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

This commit is contained in:
2026-04-21 18:00:17 +02:00
parent d900659d88
commit 16afea2768
67 changed files with 1820 additions and 2132 deletions

View File

@@ -149,15 +149,20 @@ const DynamicDemo = () => {
};
return Div({ class: 'flex flex-col gap-4 w-full' }, [
Select({
items: [
{ value: 'all', label: 'All items' },
{ value: 'fruits', label: 'Fruits' },
{ value: 'vegetables', label: 'Vegetables' }
],
value: filterType,
onchange: (e) => filterType(e.target.value)
}),
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' }
]
})
]),
Autocomplete({
items: () => allItems[filterType()],
value: selected,
@@ -165,6 +170,7 @@ const DynamicDemo = () => {
})
]);
};
Mount(DynamicDemo, '#demo-dynamic');
```

View File

@@ -69,7 +69,7 @@ const LoadingDemo = () => {
isSaving(false);
},
},
[Spinner({ value: isSaving }), "Save Changes"],
[If(isSaving, ()=>Loading()), "Save Changes"],
);
};
Mount(LoadingDemo, "#demo-loading");

View File

@@ -8,26 +8,26 @@ Form input component with icons, password toggle, and validation. Use `Label()`
## Props
| Prop | Type | Default | Description |
| :----------- | :--------------------------- | :--------- | :----------------------------------------------- |
| `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 |
| Prop | Type | Default | Description |
| :------------ | :--------------------------- | :------- | :----------------------------------------------- |
| `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
Input supports all **daisyUI Input classes**:
| Category | Keywords | Description |
| :--- | :--- | :--- |
| Style | `input-bordered`, `input-ghost` | Input style variants |
| Color | `input-primary`, `input-secondary`, `input-accent`, `input-info`, `input-success`, `input-warning`, `input-error` | Input color variants |
| Size | `input-xs`, `input-sm`, `input-md`, `input-lg` | Input size variants |
| Category | Keywords | Description |
| :------- | :---------------------------------------------------------------------------------------------------------------- | :------------------- |
| Style | `input-bordered`, `input-ghost` | Input style variants |
| Color | `input-primary`, `input-secondary`, `input-accent`, `input-info`, `input-success`, `input-warning`, `input-error` | Input color variants |
| Size | `input-xs`, `input-sm`, `input-md`, `input-lg` | Input size variants |
## Live Examples
@@ -42,15 +42,15 @@ Input supports all **daisyUI Input classes**:
```javascript
const BasicDemo = () => {
const name = $('');
const name = $("");
return Input({
placeholder: 'Enter your name',
placeholder: "Enter your name",
value: name,
oninput: (e) => name(e.target.value)
oninput: (e) => name(e.target.value),
});
};
Mount(BasicDemo, '#demo-basic');
Mount(BasicDemo, "#demo-basic");
```
### With Icon
@@ -64,16 +64,19 @@ Mount(BasicDemo, '#demo-basic');
```javascript
const IconDemo = () => {
const email = $('');
return Input({
type: 'email',
icon: "✉️",
value: email,
oninput: (e) => email(e.target.value)
});
const email = $("");
return Label({ class: "input" }, [
Icon("✉️"),
Input({
class: "grow",
type: "email",
value: email,
oninput: (e) => email(e.target.value),
}),
]);
};
Mount(IconDemo, '#demo-icon');
Mount(IconDemo, "#demo-icon");
```
### Password with Toggle
@@ -87,15 +90,27 @@ Mount(IconDemo, '#demo-icon');
```javascript
const PasswordDemo = () => {
const password = $('');
return Input({
type: 'password',
value: password,
oninput: (e) => password(e.target.value)
});
const password = $("");
const visible = $(false);
return Label({ class: "input input-bordered w-full max-w-xs" }, [
Icon("icon-[lucide--lock]"),
Input({
type: () => (visible() ? "text" : "password"),
value: password,
placeholder: "Contraseña",
class: "grow",
oninput: (e) => password(e.target.value),
}),
Swap({
value: visible,
class: "swap-rotate",
on: Icon("icon-[lucide--eye]"),
off: Icon("icon-[lucide--eye-off]"),
}),
]);
};
Mount(PasswordDemo, '#demo-password');
Mount(PasswordDemo, "#demo-password");
```
### With Floating Label
@@ -111,18 +126,20 @@ Wrap the input with `Label()` component:
```javascript
const LabelDemo = () => {
const email = $('');
return Input({
type: 'email',
const email = $("");
return Label({ class: "floating-label" }, [
Span("Text floating"),
Input({
type: "email",
label: "Email",
floating: true,
value: email,
placeholder: ' ',
oninput: (e) => email(e.target.value)
});
placeholder: "Clic here",
oninput: (e) => email(e.target.value),
}),
]);
};
Mount(LabelDemo, '#demo-label');
Mount(LabelDemo, "#demo-label");
```
### With Tooltip & label
@@ -138,18 +155,22 @@ Wrap the input with `Tooltip()` component:
```javascript
const TooltipDemo = () => {
const username = $('');
return Tooltip({ tip: 'Must be at least 3 characters' },
Input({
value: username,
label: "Username",
placeholder: 'Username',
oninput: (e) => username(e.target.value)
})
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),
}),
]),
);
};
Mount(TooltipDemo, '#demo-tooltip');
Mount(TooltipDemo, "#demo-tooltip");
```
### Error State
@@ -163,26 +184,27 @@ Mount(TooltipDemo, '#demo-tooltip');
```javascript
const ErrorDemo = () => {
const email = $('');
return Div({ class: 'w-full' }, [
Input({
type: 'email',
value: email,
placeholder: 'Enter your email',
label: 'Email',
icon: 'icon-[lucide--mail]',
validate: (value) => {
if (!value) return '';
if (!value.includes('@')) return 'Email must contain @';
if (!value.includes('.')) return 'Email must contain .';
return '';
},
oninput: (e) => email(e.target.value)
})
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")
]);
};
Mount(ErrorDemo, '#demo-error');
Mount(ErrorDemo, "#demo-error");
```
### Disabled State
@@ -197,11 +219,11 @@ Mount(ErrorDemo, '#demo-error');
```javascript
const DisabledDemo = () => {
return Input({
value: 'john.doe',
disabled: true
value: "john.doe",
disabled: true,
});
};
Mount(DisabledDemo, '#demo-disabled');
Mount(DisabledDemo, "#demo-disabled");
```
### All Variants
@@ -215,33 +237,33 @@ Mount(DisabledDemo, '#demo-disabled');
```javascript
const VariantsDemo = () => {
const text = $('');
const text = $("");
const number = $(0);
return Div({ class: 'flex flex-col gap-4' }, [
return Div({ class: "flex flex-col gap-4" }, [
Input({
placeholder: 'Type something...',
placeholder: "Type something...",
value: text,
oninput: (e) => text(e.target.value)
oninput: (e) => text(e.target.value),
}),
Input({
type: 'number',
type: "number",
value: number,
oninput: (e) => number(parseInt(e.target.value) || 0)
oninput: (e) => number(parseInt(e.target.value) || 0),
}),
Input({
type: 'date',
value: $('2024-01-01')
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({ 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" }),
]);
};
Mount(VariantsDemo, '#demo-variants');
```
Mount(VariantsDemo, "#demo-variants");
```

View File

@@ -1,22 +1,27 @@
# Select
Dropdown select component with full DaisyUI styling, reactive items, and form integration.
Dropdown select component with full DaisyUI styling and reactive options.
## Tag
`Select`
`Select`, `Options`
## Props
## Select Props
| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `label` | `string` | `-` | Label text above select |
| `items` | `Array<{value: string, label: string}> \| Signal<Array>` | `[]` | Array of items with value and label |
| `value` | `string \| Signal<string>` | `''` | Selected value |
| `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) |
| `disabled` | `boolean \| Signal<boolean>` | `false` | Disabled state |
| `onchange` | `function` | `-` | Change event handler |
## Options Props
| Prop | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `items` | `Array<string \| {value, label}> \| Signal<Array>` | `[]` | Array of items (strings or objects) |
| `placeholder` | `string` | `-` | Optional placeholder option (disabled, selected) |
## Styling
Select supports all **daisyUI Select classes**:
@@ -44,17 +49,23 @@ Select supports all **daisyUI Select classes**:
const BasicDemo = () => {
const selected = $('apple');
return Select({
label: 'Choose a fruit',
items: [
{ value: 'apple', label: '🍎 Apple' },
{ value: 'banana', label: '🍌 Banana' },
{ value: 'orange', label: '🍊 Orange' },
{ value: 'grape', label: '🍇 Grape' }
],
value: selected,
onchange: (e) => selected(e.target.value)
});
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)
}, [
Options({
items: [
{ value: 'apple', label: '🍎 Apple' },
{ value: 'banana', label: '🍌 Banana' },
{ value: 'orange', label: '🍊 Orange' },
{ value: 'grape', label: '🍇 Grape' }
]
})
])
]);
};
Mount(BasicDemo, '#demo-basic');
```
@@ -72,16 +83,22 @@ Mount(BasicDemo, '#demo-basic');
const ReactiveDemo = () => {
const selected = $('small');
return Div({ class: 'flex flex-col gap-4 w-full' }, [
Select({
label: 'Select size',
items: [
{ value: 'small', label: 'Small' },
{ value: 'medium', label: 'Medium' },
{ value: 'large', label: 'Large' }
],
value: selected,
onchange: (e) => selected(e.target.value)
}),
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)
}, [
Options({
items: [
{ value: 'small', label: 'Small' },
{ value: 'medium', label: 'Medium' },
{ value: 'large', label: 'Large' }
]
})
])
]),
Div({ class: 'alert alert-info' }, () => `You selected: ${selected()}`)
]);
};
@@ -99,16 +116,22 @@ Mount(ReactiveDemo, '#demo-reactive');
```javascript
const DisabledDemo = () => {
return Select({
label: 'Country (disabled)',
items: [
{ value: 'mx', label: 'Mexico' },
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' }
],
value: 'mx',
disabled: true
});
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
}, [
Options({
items: [
{ value: 'mx', label: 'Mexico' },
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' }
]
})
])
]);
};
Mount(DisabledDemo, '#demo-disabled');
```
@@ -139,24 +162,36 @@ const DynamicDemo = () => {
};
return Div({ class: 'flex flex-col gap-4 w-full' }, [
Select({
label: 'Category',
items: [
{ value: 'fruits', label: 'Fruits' },
{ value: 'vegetables', label: 'Vegetables' }
],
value: category,
onchange: (e) => {
category(e.target.value);
selectedItem('');
}
}),
Select({
label: 'Item',
items: () => items[category()] || [],
value: selectedItem,
onchange: (e) => selectedItem(e.target.value)
}),
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) => {
category(e.target.value);
selectedItem('');
}
}, [
Options({
items: [
{ value: 'fruits', label: 'Fruits' },
{ value: 'vegetables', label: 'Vegetables' }
]
})
])
]),
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)
}, [
Options({
items: () => items[category()] || []
})
])
]),
() => selectedItem() ? Div({ class: 'alert alert-success' }, `Selected: ${selectedItem()}`) : null
]);
};
@@ -179,38 +214,53 @@ const VariantsDemo = () => {
const ghost = $('');
return Div({ class: 'flex flex-col gap-4' }, [
Select({
label: 'Primary Select',
class: 'select-primary',
items: [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
{ value: 'option3', label: 'Option 3' }
],
value: primary,
onchange: (e) => primary(e.target.value)
}),
Select({
label: 'Secondary Select',
class: 'select-secondary',
items: [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' }
],
value: secondary,
onchange: (e) => secondary(e.target.value)
}),
Select({
label: 'Ghost Select',
class: 'select-ghost',
items: [
{ value: '', label: 'Select an option' },
{ value: 'opt1', label: 'Option 1' },
{ value: 'opt2', label: 'Option 2' }
],
value: ghost,
onchange: (e) => ghost(e.target.value)
})
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)
}, [
Options({
items: [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
{ value: 'option3', label: 'Option 3' }
]
})
])
]),
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)
}, [
Options({
items: [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' }
]
})
])
]),
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)
}, [
Options({
placeholder: 'Select an option',
items: [
{ value: 'opt1', label: 'Option 1' },
{ value: 'opt2', label: 'Option 2' }
]
})
])
])
]);
};
Mount(VariantsDemo, '#demo-variants');

View File

@@ -10,7 +10,7 @@
href="//cdn.jsdelivr.net/npm/docsify/lib/themes/vue.css"
/>
<link href="./sigpro.css" rel="stylesheet" type="text/css" />
<link href="./sigpro-ui.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

2
docs/sigpro-ui.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long