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

@@ -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
]
);