Next Preview Work Final

This commit is contained in:
2026-04-03 23:54:11 +02:00
parent 257107e198
commit a6705621d8
49 changed files with 1119 additions and 493 deletions

226
dist/sigpro-ui.js vendored
View File

@@ -68,7 +68,7 @@
Accordion: () => Accordion
});
// node_modules/sigpro/sigpro/index.js
// src/sigpro.js
var activeEffect = null;
var currentOwner = null;
var effectQueue = new Set;
@@ -272,6 +272,7 @@
}
const el = document.createElement(tag), _sanitize = (key, val) => (key === "src" || key === "href") && String(val).toLowerCase().includes("javascript:") ? "#" : val;
el._cleanups = new Set;
const boolAttrs = ["disabled", "checked", "required", "readonly", "selected", "multiple", "autofocus"];
for (let [key, val] of Object.entries(props)) {
if (key === "ref") {
typeof val === "function" ? val(el) : val.current = el;
@@ -294,33 +295,54 @@
} else if (isSignal) {
el._cleanups.add($watch2(() => {
const currentVal = _sanitize(key, val());
if (key === "class")
if (key === "class") {
el.className = currentVal || "";
else
} else if (boolAttrs.includes(key)) {
if (currentVal) {
el.setAttribute(key, "");
el[key] = true;
} else {
el.removeAttribute(key);
el[key] = false;
}
} else {
currentVal == null ? el.removeAttribute(key) : el.setAttribute(key, currentVal);
}
}));
} else {
el.setAttribute(key, _sanitize(key, val));
if (boolAttrs.includes(key)) {
if (val) {
el.setAttribute(key, "");
el[key] = true;
} else {
el.removeAttribute(key);
el[key] = false;
}
} else {
el.setAttribute(key, _sanitize(key, val));
}
}
}
const append = (child) => {
if (Array.isArray(child))
return child.forEach(append);
if (typeof child === "function") {
if (child instanceof Node) {
el.appendChild(child);
} else if (typeof child === "function") {
const marker = document.createTextNode("");
el.appendChild(marker);
let nodes = [];
el._cleanups.add($watch2(() => {
const result = child(), nextNodes = (Array.isArray(result) ? result : [result]).map((item) => item?._isRuntime ? item.container : item instanceof Node ? item : document.createTextNode(item ?? ""));
nodes.forEach((node) => {
sweep(node);
node.remove();
const res = child(), next = (Array.isArray(res) ? res : [res]).map((i) => i?._isRuntime ? i.container : i instanceof Node ? i : document.createTextNode(i ?? ""));
nodes.forEach((n) => {
sweep?.(n);
n.remove();
});
nextNodes.forEach((node) => marker.parentNode?.insertBefore(node, marker));
nodes = nextNodes;
next.forEach((n) => marker.parentNode?.insertBefore(n, marker));
nodes = next;
}));
} else
el.appendChild(child instanceof Node ? child : document.createTextNode(child ?? ""));
el.appendChild(document.createTextNode(child ?? ""));
};
append(content);
return el;
@@ -345,9 +367,9 @@
return container;
};
$if.not = (condition, thenVal, otherwiseVal) => $if(() => !(typeof condition === "function" ? condition() : condition), thenVal, otherwiseVal);
var $for = (source, render, keyFn) => {
var $for = (source, render, keyFn, tag = "div", props = { style: "display:contents" }) => {
const marker = document.createTextNode("");
const container = $html2("div", { style: "display:contents" }, [marker]);
const container = $html2(tag, props, [marker]);
let cache = new Map;
$watch2(() => {
const items = (typeof source === "function" ? source() : source) || [];
@@ -450,6 +472,7 @@
};
install(SigProCore);
}
// src/components/index.js
var exports_components = {};
__export(exports_components, {
@@ -617,10 +640,12 @@
placeholder,
disabled,
size,
validate,
...rest
} = props;
const isPassword = type === "password";
const visible = $(false);
const errorMsg = $(null);
const iconMap = {
text: "icon-[lucide--text]",
password: "icon-[lucide--lock]",
@@ -644,16 +669,35 @@
return "btn-lg";
return "btn-md";
};
const handleInput = (e) => {
const newValue = e.target.value;
if (validate) {
const result = validate(newValue);
errorMsg(result || null);
}
oninput?.(e);
};
const hasError = () => errorMsg() && errorMsg() !== "";
const inputClasses = () => {
let classes = `input w-full ${paddingLeft} ${paddingRight}`;
if (className)
classes += ` ${className}`;
if (hasError())
classes += " input-error";
return classes.trim();
};
const inputElement = $html2("input", {
...rest,
type: () => isPassword ? visible() ? "text" : "password" : type,
placeholder: placeholder || " ",
class: inputClasses,
value,
oninput: handleInput,
disabled: () => val(disabled),
"aria-invalid": () => hasError() ? "true" : "false"
});
return $html2("div", { class: "relative w-full" }, () => [
$html2("input", {
...rest,
type: () => isPassword ? visible() ? "text" : "password" : type,
placeholder: placeholder || " ",
class: ui("input w-full", `${paddingLeft} ${paddingRight} ${className || ""}`.trim()),
value,
oninput: (e) => oninput?.(e),
disabled: () => val(disabled)
}),
inputElement,
leftIcon ? $html2("div", {
class: "absolute left-3 inset-y-0 flex items-center pointer-events-none text-base-content/60"
}, leftIcon) : null,
@@ -664,7 +708,10 @@
e.preventDefault();
visible(!visible());
}
}, () => getPasswordIcon()) : null
}, () => getPasswordIcon()) : null,
$html2("div", {
class: "text-error text-xs mt-1 px-3 absolute -bottom-5 left-0"
}, () => hasError() ? errorMsg() : null)
]);
};
@@ -1353,7 +1400,7 @@
List: () => List
});
var List = (props) => {
const { class: className, items, header, render, keyFn = (item, index) => index, ...rest } = props;
const { class: className, items, header, render, keyFn = (item, index) => item.id ?? index, ...rest } = props;
const listItems = $for(items, (item, index) => $html2("li", { class: "list-row" }, [render(item, index)]), keyFn);
return $html2("ul", {
...rest,
@@ -1607,6 +1654,7 @@
const pinRowsClass = val(pinRows) ? "table-pin-rows" : "";
return ui("table", className, zebraClass, pinRowsClass);
};
const getInternalKeyFn = keyFn || ((item, idx) => item.id || idx);
return $html2("div", { class: "overflow-x-auto w-full bg-base-100 rounded-box border border-base-300" }, [
$html2("table", { ...rest, class: tableClass }, [
$html2("thead", {}, [
@@ -1614,25 +1662,27 @@
]),
$html2("tbody", {}, [
$for(items, (item, index) => {
const it = () => {
const currentItems = val(items);
const key = getInternalKeyFn(item, index);
return currentItems.find((u, i) => getInternalKeyFn(u, i) === key) || item;
};
return $html2("tr", { class: "hover" }, columns.map((col) => {
const cellContent = () => {
const latestItem = it();
if (col.render)
return col.render(item, index);
const value = item[col.key];
return val(value);
return col.render(latestItem, index);
return val(latestItem[col.key]);
};
return $html2("td", { class: col.class || "" }, [cellContent]);
}));
}, keyFn || ((item, idx) => item.id || idx)),
}, getInternalKeyFn),
$if(() => val(items).length === 0, () => $html2("tr", {}, [
$html2("td", { colspan: columns.length, class: "text-center p-10 opacity-50" }, [
val(empty)
])
]))
]),
$if(() => columns.some((c) => c.footer), () => $html2("tfoot", {}, [
$html2("tr", {}, columns.map((col) => $html2("th", {}, col.footer || "")))
]))
])
])
]);
};
@@ -1645,55 +1695,55 @@
var Tabs = (props) => {
const { items, class: className, ...rest } = props;
const itemsSignal = typeof items === "function" ? items : () => items || [];
const name = `tabs-${Math.random().toString(36).slice(2, 9)}`;
const getActiveIndex = () => {
const arr = itemsSignal();
const idx = arr.findIndex((it) => val(it.active) === true);
return idx === -1 ? 0 : idx;
};
const activeIndex = $(getActiveIndex);
const updateActiveIndex = () => {
const newIndex = getActiveIndex();
if (newIndex !== activeIndex())
activeIndex(newIndex);
};
$watch(() => updateActiveIndex());
return $html2("div", {
...rest,
class: ui("tabs", className || "tabs-box")
}, [
$for(itemsSignal, (it, idx) => {
const isChecked = () => activeIndex() === idx;
const getLabelText = () => {
const label = typeof it.label === "function" ? it.label() : it.label;
return typeof label === "string" ? label : `Tab ${idx + 1}`;
};
return [
$html2("input", {
type: "radio",
name,
class: "tab",
"aria-label": getLabelText(),
checked: isChecked,
disabled: () => val(it.disabled),
onchange: (e) => {
if (e.target.checked && !val(it.disabled)) {
const activeIndex = $(0);
$watch(() => {
const idx = itemsSignal().findIndex((it) => val(it.active) === true);
if (idx !== -1 && idx !== activeIndex())
activeIndex(idx);
});
return $html2("div", { ...rest, class: "w-full" }, [
$html2("div", {
role: "tablist",
class: ui("tabs", className || "tabs-box")
}, () => {
const list = itemsSignal();
return list.map((it, idx) => {
const isSelected = () => activeIndex() === idx;
const tab = $html2("button", {
role: "tab",
class: () => ui("tab", isSelected() ? "tab-active" : ""),
onclick: (e) => {
e.preventDefault();
if (!val(it.disabled)) {
if (it.onclick)
it.onclick();
if (typeof it.active === "function")
it.active(true);
activeIndex(idx);
}
}
}),
$html2("div", {
});
$watch(() => {
const content = val(it.label);
if (content instanceof Node) {
tab.replaceChildren(content);
} else {
tab.textContent = String(content);
}
});
return tab;
});
}),
$html2("div", { class: "tab-panels" }, () => {
return itemsSignal().map((it, idx) => {
const isVisible = () => activeIndex() === idx;
return $html2("div", {
role: "tabpanel",
class: "tab-content bg-base-100 border-base-300 p-6",
style: () => isChecked() ? "display: block" : "display: none"
style: () => isVisible() ? "display: block" : "display: none"
}, [
typeof it.content === "function" ? it.content() : it.content
])
];
}, (it, idx) => idx)
() => typeof it.content === "function" ? it.content() : it.content
]);
});
})
]);
};
@@ -1710,27 +1760,29 @@
warning: "icon-[lucide--alert-triangle]",
error: "icon-[lucide--alert-circle]"
};
const itemsSource = typeof items === "function" ? items : () => items || [];
return $html2("ul", {
...rest,
class: () => ui(`timeline ${val(vertical) ? "timeline-vertical" : "timeline-horizontal"} ${val(compact) ? "timeline-compact" : ""}`, className)
}, [
$for(itemsSource, (item, i) => {
}, () => {
const list = (typeof items === "function" ? items() : items) || [];
return list.map((item, i) => {
const isFirst = i === 0;
const isLast = i === itemsSource().length - 1;
const isLast = i === list.length - 1;
const itemType = item.type || "success";
const isCompleted = () => val(item.completed);
const prevCompleted = () => i > 0 && val(list[i - 1].completed);
const renderSlot = (content) => typeof content === "function" ? content() : content;
return $html2("li", { class: "flex-1" }, [
!isFirst ? $html2("hr", { class: () => item.completed ? "bg-primary" : "" }) : null,
$html2("div", { class: "timeline-start" }, () => renderSlot(item.title)),
$html2("div", { class: "timeline-middle" }, () => [
item.icon ? getIcon(item.icon) : getIcon(iconMap[itemType] || iconMap.success)
!isFirst ? $html2("hr", { class: () => prevCompleted() ? "bg-primary" : "" }) : null,
$html2("div", { class: "timeline-start" }, [() => renderSlot(item.title)]),
$html2("div", { class: "timeline-middle" }, [
() => item.icon ? getIcon(item.icon) : getIcon(iconMap[itemType] || iconMap.success)
]),
$html2("div", { class: "timeline-end timeline-box shadow-sm" }, () => renderSlot(item.detail)),
!isLast ? $html2("hr", { class: () => item.completed ? "bg-primary" : "" }) : null
$html2("div", { class: "timeline-end timeline-box shadow-sm" }, [() => renderSlot(item.detail)]),
!isLast ? $html2("hr", { class: () => isCompleted() ? "bg-primary" : "" }) : null
]);
}, (item, i) => item.id || i)
]);
});
});
};
// src/components/Toast.js

File diff suppressed because one or more lines are too long