Migrating new components
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s

This commit is contained in:
2026-04-20 23:31:14 +02:00
parent 6fc32614b1
commit d900659d88
59 changed files with 1824 additions and 1554 deletions

9
components/Button.js Normal file
View File

@@ -0,0 +1,9 @@
import { Tag } from "sigpro";
export const Button = (props, children) => {
const { class: className, ...rest } = props;
return Tag("button", {
...rest,
class: `btn ${className || ''}`.trim()
}, children);
};

83
components/Colorpicker.js Normal file
View File

@@ -0,0 +1,83 @@
// components/Colorpicker.js
import { $, Tag, If } from "sigpro";
export const Colorpicker = (props) => {
const { class: className, value, label, ...rest } = props;
const isOpen = $(false);
const palette = [
...["#000", "#1A1A1A", "#333", "#4D4D4D", "#666", "#808080", "#B3B3B3", "#FFF"],
...["#450a0a", "#7f1d1d", "#991b1b", "#b91c1c", "#dc2626", "#ef4444", "#f87171", "#fca5a5"],
...["#431407", "#7c2d12", "#9a3412", "#c2410c", "#ea580c", "#f97316", "#fb923c", "#ffedd5"],
...["#713f12", "#a16207", "#ca8a04", "#eab308", "#facc15", "#fde047", "#fef08a", "#fff9c4"],
...["#064e3b", "#065f46", "#059669", "#10b981", "#34d399", "#4ade80", "#84cc16", "#d9f99d"],
...["#082f49", "#075985", "#0284c7", "#0ea5e9", "#38bdf8", "#7dd3fc", "#22d3ee", "#cffafe"],
...["#1e1b4b", "#312e81", "#4338ca", "#4f46e5", "#6366f1", "#818cf8", "#a5b4fc", "#e0e7ff"],
...["#2e1065", "#4c1d95", "#6d28d9", "#7c3aed", "#8b5cf6", "#a855f7", "#d946ef", "#fae8ff"],
];
const getColor = () => {
const v = value;
return (typeof v === "function" ? v() : v) || "#000000";
};
return Tag("div", { class: `relative w-fit ${className || ''}`.trim() }, [
Tag(
"button",
{
type: "button",
class: "btn px-3 bg-base-100 border-base-300 hover:border-primary/50 flex items-center gap-2 shadow-sm font-normal normal-case",
onclick: (e) => {
e.stopPropagation();
isOpen(!isOpen());
},
...rest,
},
[
Tag("div", {
class: "size-5 rounded-sm shadow-inner border border-black/10 shrink-0",
style: () => `background-color: ${getColor()}`,
}),
label ? Tag("span", { class: "opacity-80" }, label) : null,
],
),
If(isOpen, () =>
Tag(
"div",
{
class: "absolute left-0 mt-2 p-3 bg-base-100 border border-base-300 shadow-2xl rounded-box z-[110] w-64 select-none",
onclick: (e) => e.stopPropagation(),
},
[
Tag(
"div",
{ class: "grid grid-cols-8 gap-1" },
palette.map((c) =>
Tag("button", {
type: "button",
style: `background-color: ${c}`,
class: () => {
const active = getColor().toLowerCase() === c.toLowerCase();
return `size-6 rounded-sm cursor-pointer transition-all hover:scale-125 hover:z-10 active:scale-95 outline-none border border-black/5 p-0 min-h-0
${active ? "ring-2 ring-offset-1 ring-primary z-10 scale-110" : ""}`;
},
onclick: () => {
if (typeof value === "function") value(c);
isOpen(false);
},
}),
),
),
],
),
),
If(isOpen, () =>
Tag("div", {
class: "fixed inset-0 z-[100]",
onclick: () => isOpen(false),
}),
),
]);
};

7
components/Icon.js Normal file
View File

@@ -0,0 +1,7 @@
// components/Icon.js
import { Tag } from "sigpro";
export const Icon = (iconClass) => {
if (!iconClass) return null;
return Tag("span", { class: iconClass });
};

10
components/Input.js Normal file
View File

@@ -0,0 +1,10 @@
import { Tag } from "sigpro";
export const Input = (props) => {
const { class: className, type = "text", ...rest } = props;
return Tag("input", {
...rest,
type,
class: `input ${className || ''}`.trim()
});
};

View File

@@ -1,4 +1,4 @@
// components/Spinner.js
// components/Loading.js
import { Tag } from "sigpro";
export const Spinner = (props) => {

25
components/Select.js Normal file
View File

@@ -0,0 +1,25 @@
// components/Select.js
import { Tag, For } from "sigpro";
export const Select = (props, children) => {
const { class: className, ...rest } = props;
return Tag("select", {
...rest,
class: `select ${className || ''}`.trim()
}, children);
};
export const Options = (props) => {
const { items, placeholder, placeholderDisabled = true, ...rest } = props;
const itemArray = typeof items === "function" ? items() : (items || []);
return [
placeholder && Tag("option", { disabled: placeholderDisabled, selected: true }, placeholder),
For(itemArray, (item) => {
const val = typeof item === "string" ? item : item.value;
const label = typeof item === "string" ? item : item.label;
return Tag("option", { value: val, ...rest }, label);
})
];
};

27
components/Stat.js Normal file
View File

@@ -0,0 +1,27 @@
// components/Stats.js
import { Tag } from "sigpro";
export const Stats = (props, children) => {
const { class: className, vertical = false, ...rest } = props;
const direction = vertical ? "stats-vertical" : "stats-horizontal";
return Tag("div", {
...rest,
class: `stats ${direction} ${className || ''}`.trim()
}, children);
};
export const Stat = (props) => {
const { class: className, label, value, desc, icon, actions, children, ...rest } = props;
if (children !== undefined) {
return Tag("div", { ...rest, class: `stat ${className || ''}`.trim() }, children);
}
return Tag("div", { ...rest, class: `stat ${className || ''}`.trim() }, [
icon && Tag("div", { class: "stat-figure" }, icon),
label && Tag("div", { class: "stat-title" }, label),
value && Tag("div", { class: "stat-value" }, value),
desc && Tag("div", { class: "stat-desc" }, desc),
actions && Tag("div", { class: "stat-actions" }, actions)
]);
};

9
components/Textarea.js Normal file
View File

@@ -0,0 +1,9 @@
import { Tag } from "sigpro";
export const Textarea = (props) => {
const { class: className, ...rest } = props;
return Tag("textarea", {
...rest,
class: `textarea ${className || ''}`.trim()
});
};

1393
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

1393
dist/sigpro-ui.js vendored

File diff suppressed because it is too large Load Diff

14
dist/sigpro-ui.min.js vendored

File diff suppressed because one or more lines are too long

248
dist/sigpro.css vendored
View File

@@ -1500,6 +1500,42 @@
}
}
}
.radial-progress {
@layer daisyui.l1.l2.l3 {
position: relative;
display: inline-grid;
height: var(--size);
width: var(--size);
place-content: center;
border-radius: calc(infinity * 1px);
background-color: transparent;
vertical-align: middle;
box-sizing: content-box;
--value: 0;
--size: 5rem;
--thickness: calc(var(--size) / 10);
--radialprogress: calc(var(--value) * 1%);
transition: --radialprogress 0.3s linear;
&:before {
position: absolute;
inset: calc(0.25rem * 0);
border-radius: calc(infinity * 1px);
content: "";
background: radial-gradient(farthest-side, currentColor 98%, #0000) top/var(--thickness) var(--thickness) no-repeat, conic-gradient(currentColor var(--radialprogress), #0000 0);
webkit-mask: radial-gradient( farthest-side, #0000 calc(100% - var(--thickness)), #000 calc(100% + 0.5px - var(--thickness)) );
mask: radial-gradient( farthest-side, #0000 calc(100% - var(--thickness)), #000 calc(100% + 0.5px - var(--thickness)) );
}
&:after {
position: absolute;
border-radius: calc(infinity * 1px);
background-color: currentcolor;
transition: transform 0.3s linear;
content: "";
inset: calc(50% - var(--thickness) / 2);
transform: rotate(calc(var(--value) * 3.6deg - 90deg)) translate(calc(var(--size) / 2 - 50%));
}
}
}
.list {
@layer daisyui.l1.l2.l3 {
display: flex;
@@ -2134,6 +2170,34 @@
}
}
}
.chat-bubble {
@layer daisyui.l1.l2.l3 {
position: relative;
display: block;
width: fit-content;
border-radius: var(--radius-field);
background-color: var(--color-base-300);
padding-inline: calc(0.25rem * 4);
padding-block: calc(0.25rem * 2);
color: var(--color-base-content);
grid-row-end: 3;
min-height: 2rem;
min-width: 2.5rem;
max-width: 90%;
&:before {
position: absolute;
bottom: calc(0.25rem * 0);
height: calc(0.25rem * 3);
width: calc(0.25rem * 3);
background-color: inherit;
content: "";
mask-repeat: no-repeat;
mask-image: var(--mask-chat);
mask-position: 0px -1px;
mask-size: 0.8125rem;
}
}
}
.select {
@layer daisyui.l1.l2.l3 {
border: var(--border) solid #0000;
@@ -3689,6 +3753,12 @@
font-size: 0.75rem;
}
}
.stat-actions {
@layer daisyui.l1.l2.l3 {
grid-column-start: 1;
white-space: nowrap;
}
}
.col-start-1 {
grid-column-start: 1;
}
@@ -3698,6 +3768,28 @@
.col-start-3 {
grid-column-start: 3;
}
.chat-image {
@layer daisyui.l1.l2.l3 {
grid-row: span 2 / span 2;
align-self: flex-end;
}
}
.chat-footer {
@layer daisyui.l1.l2.l3 {
grid-row-start: 3;
display: flex;
gap: calc(0.25rem * 1);
font-size: 0.6875rem;
}
}
.chat-header {
@layer daisyui.l1.l2.l3 {
grid-row-start: 1;
display: flex;
gap: calc(0.25rem * 1);
font-size: 0.6875rem;
}
}
.row-start-2 {
grid-row-start: 2;
}
@@ -3973,6 +4065,14 @@
.ml-6 {
margin-left: calc(var(--spacing) * 6);
}
.carousel-item {
@layer daisyui.l1.l2.l3 {
box-sizing: content-box;
display: flex;
flex: none;
scroll-snap-align: start;
}
}
.status {
@layer daisyui.l1.l2.l3 {
display: inline-block;
@@ -4293,6 +4393,78 @@
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='M18 6L6 18M6 6l12 12'/%3E%3C/svg%3E");
}
.kbd {
box-shadow: none;
@layer daisyui.l1.l2.l3 {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-field);
background-color: var(--color-base-200);
vertical-align: middle;
padding-inline: 0.5em;
border: var(--border) solid var(--color-base-content);
@supports (color: color-mix(in lab, red, red)) {
border: var(--border) solid color-mix(in srgb, var(--color-base-content) 20%, #0000);
}
border-bottom: calc(var(--border) + 1px) solid var(--color-base-content);
@supports (color: color-mix(in lab, red, red)) {
border-bottom: calc(var(--border) + 1px) solid color-mix(in srgb, var(--color-base-content) 20%, #0000);
}
--size: calc(var(--size-selector, 0.25rem) * 6);
font-size: 0.875rem;
height: var(--size);
min-width: var(--size);
}
}
.text-rotate {
height: 1lh;
@layer daisyui.l1.l2.l3 {
display: inline-block;
overflow: hidden;
vertical-align: bottom;
white-space: nowrap;
transition-property: none;
--duration: var(--tw-duration);
> * {
display: grid;
justify-items: start;
height: calc(var(--items, 1) * 100%);
&:has(*:nth-child(2)) {
--items: 2;
animation: rotator var(--duration, 10s) linear(0 0% 49%, 0.5 50% 99%, 1 100% 100%) infinite;
}
&:has(*:nth-child(3)) {
--items: 3;
animation: rotator var(--duration, 10s) linear(0 0% 32%, 0.333333 33% 65%, 0.666666 66% 99%, 1 100% 100%) infinite;
}
&:has(*:nth-child(4)) {
--items: 4;
animation: rotator var(--duration, 10s) linear(0 0% 24%, 0.25 25% 49%, 0.5 50% 74%, 0.75 75% 99%, 1 100% 100%) infinite;
}
&:has(*:nth-child(5)) {
--items: 5;
animation: rotator var(--duration, 10s) linear(0 0% 19%, 0.2 20% 39%, 0.4 40% 59%, 0.6 60% 79%, 0.8 80% 99%, 1 100% 100%) infinite;
}
&:has(*:nth-child(6)) {
--items: 6;
animation: rotator var(--duration, 10s) linear( 0 0% 15%, 0.16666 16% 32%, 0.333333 33% 49%, 0.5 50% 65%, 0.666666 66% 82%, 0.833333 83% 99%, 1 100% 100% ) infinite;
}
> * {
align-content: baseline;
clip-path: inset(0.5px 0px 0.5px 0px);
&:nth-child(1) {
translate: var(--first-item-position);
}
}
}
&:hover {
> * {
animation-play-state: paused;
}
}
}
}
.tabs {
@layer daisyui.l1.l2.l3 {
display: flex;
@@ -4396,6 +4568,20 @@
}
}
}
.carousel {
@layer daisyui.l1.l2.l3 {
display: inline-flex;
overflow-x: scroll;
scroll-snap-type: x mandatory;
scrollbar-width: none;
@media (prefers-reduced-motion: no-preference) {
scroll-behavior: smooth;
}
&::-webkit-scrollbar {
display: none;
}
}
}
.alert {
border-width: var(--border);
border-color: var(--alert-border-color, var(--color-base-200));
@@ -4438,6 +4624,23 @@
grid-auto-rows: max-content;
}
}
.chat {
@layer daisyui.l1.l2.l3 {
display: grid;
grid-auto-rows: min-content;
column-gap: calc(0.25rem * 3);
padding-block: calc(0.25rem * 1);
--mask-chat: url("data:image/svg+xml,%3csvg width='13' height='13' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill='black' d='M0 11.5004C0 13.0004 2 13.0004 2 13.0004H12H13V0.00036329L12.5 0C12.5 0 11.977 2.09572 11.8581 2.50033C11.6075 3.35237 10.9149 4.22374 9 5.50036C6 7.50036 0 10.0004 0 11.5004Z'/%3e%3c/svg%3e");
}
}
.card-actions {
@layer daisyui.l1.l2.l3 {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
gap: calc(0.25rem * 2);
}
}
.card-title {
@layer daisyui.l1.l2.l3 {
display: flex;
@@ -4557,6 +4760,9 @@
.h-3\.5 {
height: calc(var(--spacing) * 3.5);
}
.h-4 {
height: calc(var(--spacing) * 4);
}
.h-8 {
height: calc(var(--spacing) * 8);
}
@@ -4792,6 +4998,22 @@
.transform {
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
}
.skeleton {
@layer daisyui.l1.l2.l3 {
border-radius: var(--radius-box);
background-color: var(--color-base-300);
@media (prefers-reduced-motion: reduce) {
transition-duration: 15s;
}
will-change: background-position;
background-image: linear-gradient( 105deg, #0000 0% 40%, var(--color-base-100) 50%, #0000 60% 100% );
background-size: 200% auto;
background-position-x: -50%;
@media (prefers-reduced-motion: no-preference) {
animation: skeleton 1.8s ease-in-out infinite;
}
}
}
.animate-pulse {
animation: var(--animate-pulse);
}
@@ -4804,6 +5026,32 @@
.list-none {
list-style-type: none;
}
.stats-horizontal {
@layer daisyui.l1.l2 {
grid-auto-flow: column;
overflow-x: auto;
.stat:not(:last-child) {
border-inline-end: var(--border) dashed currentColor;
@supports (color: color-mix(in lab, red, red)) {
border-inline-end: var(--border) dashed color-mix(in oklab, currentColor 10%, #0000);
}
border-block-end: none;
}
}
}
.stats-vertical {
@layer daisyui.l1.l2 {
grid-auto-flow: row;
overflow-y: auto;
.stat:not(:last-child) {
border-inline-end: none;
border-block-end: var(--border) dashed currentColor;
@supports (color: color-mix(in lab, red, red)) {
border-block-end: var(--border) dashed color-mix(in oklab, currentColor 10%, #0000);
}
}
}
}
.grid-cols-1 {
grid-template-columns: repeat(1, minmax(0, 1fr));
}

2
dist/sigpro.min.css vendored

File diff suppressed because one or more lines are too long

14
docs/sigpro-ui.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,38 +1,47 @@
import * as AccordionModule from './src/components/Accordion.js';
import * as AlertModule from './src/components/Alert.js';
import * as AutocompleteModule from './src/components/Autocomplete.js';
import * as BadgeModule from './src/components/Badge.js';
import * as ButtonModule from './src/components/Button.js';
import * as CheckboxModule from './src/components/Checkbox.js';
import * as ColorpickerModule from './src/components/Colorpicker.js';
import * as DatepickerModule from './src/components/Datepicker.js';
import * as DrawerModule from './src/components/Drawer.js';
import * as DropdownModule from './src/components/Dropdown.js';
import * as FabModule from './src/components/Fab.js';
import * as FieldsetModule from './src/components/Fieldset.js';
import * as FileinputModule from './src/components/Fileinput.js';
import * as IconModule from './src/components/Icon.js';
import * as IndicatorModule from './src/components/Indicator.js';
import * as InputModule from './src/components/Input.js';
import * as LabelModule from './src/components/Label.js';
import * as ListModule from './src/components/List.js';
import * as MenuModule from './src/components/Menu.js';
import * as ModalModule from './src/components/Modal.js';
import * as NavbarModule from './src/components/Navbar.js';
import * as RadioModule from './src/components/Radio.js';
import * as RangeModule from './src/components/Range.js';
import * as RatingModule from './src/components/Rating.js';
import * as SelectModule from './src/components/Select.js';
import * as SpinnerModule from './src/components/Spinner.js';
import * as StackModule from './src/components/Stack.js';
import * as StatModule from './src/components/Stat.js';
import * as SwapModule from './src/components/Swap.js';
import * as TableModule from './src/components/Table.js';
import * as TabsModule from './src/components/Tabs.js';
import * as TimelineModule from './src/components/Timeline.js';
import * as ToastModule from './src/components/Toast.js';
import * as TooltipModule from './src/components/Tooltip.js';
import { Locale, tt } from './src/utils.js';
import * as AccordionModule from './components/Accordion.js';
import * as AlertModule from './components/Alert.js';
import * as AutocompleteModule from './components/Autocomplete.js';
import * as BadgeModule from './components/Badge.js';
import * as ButtonModule from './components/Button.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 DrawerModule from './components/Drawer.js';
import * as DropdownModule from './components/Dropdown.js';
import * as FabModule from './components/Fab.js';
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 KdbModule from './components/Kdb.js';
import * as InputModule from './components/Input.js';
import * as ListModule from './components/List.js';
import * as LoadingModule from './components/Loading.js';
import * as MenuModule from './components/Menu.js';
import * as ModalModule from './components/Modal.js';
import * as NavbarModule from './components/Navbar.js';
import * as RadialModule from './components/Radial.js';
import * as RadioModule from './components/Radio.js';
import * as RangeModule from './components/Range.js';
import * as RatingModule from './components/Rating.js';
import * as SkeletonModule from './components/Skeleton.js';
import * as SelectModule from './components/Select.js';
import * as StackModule from './components/Stack.js';
import * as StatModule from './components/Stat.js';
import * as StepsModule from './components/Stat.js';
import * as SwapModule from './components/Swap.js';
import * as TableModule from './components/Table.js';
import * as TabsModule from './components/Tabs.js';
import * as TextareaModule from './components/Textarea.js';
import * as TextRotateModule from './components/TextRotate.js';
import * as TimelineModule from './components/Timeline.js';
import * as ToastModule from './components/Toast.js';
import * as ToggleModule from './components/Toggle.js';
import * as TooltipModule from './components/Tooltip.js';
import { Locale, tt } from './utils.js';
export const Components = {
...AccordionModule,
@@ -40,6 +49,9 @@ export const Components = {
...AutocompleteModule,
...BadgeModule,
...ButtonModule,
...CardModule,
...CarouselModule,
...ChatModule,
...CheckboxModule,
...ColorpickerModule,
...DatepickerModule,
@@ -50,24 +62,30 @@ export const Components = {
...FileinputModule,
...IconModule,
...IndicatorModule,
...KdbModule,
...InputModule,
...LabelModule,
...ListModule,
...LoadingModule,
...MenuModule,
...ModalModule,
...NavbarModule,
...RadialModule,
...RadioModule,
...RangeModule,
...RatingModule,
...SkeletonModule,
...SelectModule,
...SpinnerModule,
...StackModule,
...StatModule,
...StepsModule,
...SwapModule,
...TableModule,
...TabsModule,
...TextareaModule,
...TextRotateModule,
...TimelineModule,
...ToastModule,
...ToggleModule,
...TooltipModule
};

View File

@@ -44,9 +44,9 @@
},
"scripts": {
"clean": "rm -rf ./dist ./css/*.css ./docs/*.js ./docs/*.css",
"build:cssmin": "tailwindcss -i ./src/sigpro.css -o ./dist/sigpro.min.css --content './src/**/*.js' --minify",
"build:css": "tailwindcss -i ./src/sigpro.css -o ./dist/sigpro.css --content './src/**/*.js'",
"build:cssdocs": "tailwindcss -i ./src/sigpro.css -o ./docs/sigpro.css --content './src/**/*.js' --minify",
"build:cssmin": "tailwindcss -i ./sigpro.css -o ./dist/sigpro.min.css --content './src/**/*.js' --minify",
"build:css": "tailwindcss -i ./sigpro.css -o ./dist/sigpro.css --content './src/**/*.js'",
"build:cssdocs": "tailwindcss -i ./sigpro.css -o ./docs/sigpro.css --content './src/**/*.js' --minify",
"build:js": "bun run build:js:iife && bun run build:js:esm",
"build:js:iife": "bun build ./index.js --bundle --outfile=./dist/sigpro-ui.js --format=iife --global-name=SigProUI && bun build ./index.js --bundle --outfile=./dist/sigpro-ui.min.js --format=iife --global-name=SigProUI --minify",
"build:js:esm": "bun build ./index.js --bundle --outfile=./dist/sigpro-ui.esm.js --format=esm && bun build ./index.js --bundle --outfile=./dist/sigpro-ui.esm.min.js --format=esm --minify",

View File

@@ -147,7 +147,7 @@
}
}
@layer utilities {
/* @layer utilities {
button {
@apply btn;
}
@@ -207,7 +207,7 @@
[role="alert"] {
@apply alert;
}
}
} */
/* sigpro-ui daisyUI classes - extracted from components */

View File

@@ -1,14 +0,0 @@
// components/Input.js
import { Tag } from "sigpro";
export const Input = (props) => {
const { type = "text", value, oninput, class: className, ...rest } = props;
return Tag("input", {
...rest,
type,
value,
oninput,
class: className,
});
};

View File

@@ -1,10 +0,0 @@
// components/Stat.js
import { Tag } from "sigpro";
export const Stat = (props, children) => {
const { class: className, ...rest } = props;
return Tag("div", {
...rest,
class: `stat ${className || ''}`.trim()
}, children);
};