@spaethtech/svelte-ui 0.19.1-dev.98.32fa323 → 0.20.1-dev.101.530be6a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Alert.svelte +11 -5
- package/dist/components/Alert.svelte.d.ts +2 -0
- package/dist/components/Badge/Badge.svelte +9 -2
- package/dist/components/Badge/Badge.svelte.d.ts +2 -1
- package/dist/components/CardFooter.svelte +12 -1
- package/dist/components/CardFooter.svelte.d.ts +3 -0
- package/dist/components/EmailInput.svelte +2 -1
- package/dist/components/EmailInput.svelte.d.ts +2 -1
- package/dist/components/NumberInput.svelte +2 -1
- package/dist/components/NumberInput.svelte.d.ts +2 -1
- package/dist/components/PasswordInput.svelte +2 -1
- package/dist/components/PasswordInput.svelte.d.ts +2 -1
- package/dist/components/SearchInput.svelte +2 -1
- package/dist/components/SearchInput.svelte.d.ts +2 -1
- package/dist/components/field-chrome.d.ts +22 -0
- package/dist/components/field-chrome.js +1 -0
- package/docs/components.md +5 -1
- package/package.json +1 -1
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
variant?: AlertVariant;
|
|
15
15
|
size?: Responsive<Size>;
|
|
16
16
|
text?: string;
|
|
17
|
+
/** Optional bold heading rendered above the body (`text`/`children`). Icon top-aligns when set. */
|
|
18
|
+
title?: string;
|
|
17
19
|
/** Faint tinted background in addition to the bordered + coloured text. */
|
|
18
20
|
filled?: boolean;
|
|
19
21
|
/** Drop the visible frame while keeping the 1px box: border colour = the alert's own background
|
|
@@ -31,6 +33,7 @@
|
|
|
31
33
|
variant = "info",
|
|
32
34
|
size = "md",
|
|
33
35
|
text = "",
|
|
36
|
+
title,
|
|
34
37
|
filled = false,
|
|
35
38
|
borderless = false,
|
|
36
39
|
icon,
|
|
@@ -86,13 +89,13 @@
|
|
|
86
89
|
` color: ${textColor};` +
|
|
87
90
|
(filled ? ` background-color: ${bgColor};` : ""),
|
|
88
91
|
);
|
|
89
|
-
const has = $derived(!!children || !!text);
|
|
92
|
+
const has = $derived(!!children || !!text || !!title);
|
|
90
93
|
</script>
|
|
91
94
|
|
|
92
95
|
{#if has}
|
|
93
96
|
<div
|
|
94
97
|
role="alert"
|
|
95
|
-
class="flex items-center [border-radius:var(--ui-border-radius)] border {responsiveClasses(
|
|
98
|
+
class="flex {title ? 'items-start' : 'items-center'} [border-radius:var(--ui-border-radius)] border {responsiveClasses(
|
|
96
99
|
size,
|
|
97
100
|
sizeClass,
|
|
98
101
|
)} {cls}"
|
|
@@ -104,9 +107,12 @@
|
|
|
104
107
|
>{@render icon()}</span
|
|
105
108
|
>
|
|
106
109
|
{/if}
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
<div class="flex min-w-0 flex-col">
|
|
111
|
+
{#if title}<span class="font-semibold">{title}</span>{/if}
|
|
112
|
+
<span class="min-w-0"
|
|
113
|
+
>{#if children}{@render children()}{:else}{text}{/if}</span
|
|
114
|
+
>
|
|
115
|
+
</div>
|
|
110
116
|
{#if icon && iconPosition === "right"}
|
|
111
117
|
<span
|
|
112
118
|
class="ml-auto inline-flex shrink-0 [&_svg]:fill-current {responsiveClasses(
|
|
@@ -11,6 +11,8 @@ interface Props {
|
|
|
11
11
|
variant?: AlertVariant;
|
|
12
12
|
size?: Responsive<Size>;
|
|
13
13
|
text?: string;
|
|
14
|
+
/** Optional bold heading rendered above the body (`text`/`children`). Icon top-aligns when set. */
|
|
15
|
+
title?: string;
|
|
14
16
|
/** Faint tinted background in addition to the bordered + coloured text. */
|
|
15
17
|
filled?: boolean;
|
|
16
18
|
/** Drop the visible frame while keeping the 1px box: border colour = the alert's own background
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { uiI18n } from "../../i18n.js";
|
|
3
3
|
const i18n = uiI18n();
|
|
4
4
|
import type { Snippet } from "svelte";
|
|
5
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
5
6
|
import Close from "~icons/mdi/close";
|
|
6
7
|
import type { Size } from "../../types/sizes.js";
|
|
7
8
|
import { responsiveClasses, type Responsive } from "../../types/responsive.js";
|
|
@@ -27,7 +28,10 @@
|
|
|
27
28
|
| "danger"
|
|
28
29
|
| "ghost";
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
// Spreads leftover HTML attributes (`class`, `data-*`, `aria-*`, `title`, `id`, event handlers, …)
|
|
32
|
+
// onto the chip's root element. `style` is OMITTED — the chip computes its own themed `style`
|
|
33
|
+
// (fill/border/text `color-mix`); a passthrough would clobber it. Use `class` for overrides.
|
|
34
|
+
interface Props extends Omit<HTMLAttributes<HTMLElement>, "style"> {
|
|
31
35
|
text?: string;
|
|
32
36
|
variant?: BadgeVariant;
|
|
33
37
|
size?: Responsive<Size>;
|
|
@@ -55,6 +59,8 @@
|
|
|
55
59
|
href,
|
|
56
60
|
ondismiss,
|
|
57
61
|
children,
|
|
62
|
+
class: cls = "",
|
|
63
|
+
...rest
|
|
58
64
|
}: Props = $props();
|
|
59
65
|
|
|
60
66
|
// Every variant maps to a library-wide colour token — no Tailwind
|
|
@@ -128,12 +134,13 @@
|
|
|
128
134
|
{#if hasContent}
|
|
129
135
|
<svelte:element
|
|
130
136
|
this={href ? "a" : "span"}
|
|
137
|
+
{...rest}
|
|
131
138
|
{href}
|
|
132
139
|
class="inline-flex items-center gap-1 border no-underline select-none {href
|
|
133
140
|
? 'cursor-pointer hover:brightness-95'
|
|
134
141
|
: 'cursor-default'} {responsiveClasses(size, sizeClass)} {rounded
|
|
135
142
|
? 'rounded-full'
|
|
136
|
-
: 'rounded'} transition-[filter,background-color,border-color] duration-150"
|
|
143
|
+
: 'rounded'} transition-[filter,background-color,border-color] duration-150 {cls}"
|
|
137
144
|
{style}
|
|
138
145
|
>
|
|
139
146
|
<span class="truncate">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
2
3
|
import type { Size } from "../../types/sizes.js";
|
|
3
4
|
import { type Responsive } from "../../types/responsive.js";
|
|
4
5
|
/**
|
|
@@ -12,7 +13,7 @@ import { type Responsive } from "../../types/responsive.js";
|
|
|
12
13
|
* text stays high-contrast against the background.
|
|
13
14
|
*/
|
|
14
15
|
type BadgeVariant = "neutral" | "default" | "primary" | "secondary" | "success" | "info" | "warning" | "danger" | "ghost";
|
|
15
|
-
interface Props {
|
|
16
|
+
interface Props extends Omit<HTMLAttributes<HTMLElement>, "style"> {
|
|
16
17
|
text?: string;
|
|
17
18
|
variant?: BadgeVariant;
|
|
18
19
|
size?: Responsive<Size>;
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
variant = "neutral",
|
|
18
18
|
size = "md",
|
|
19
19
|
separator = true,
|
|
20
|
+
align = "right",
|
|
20
21
|
class: cls = "",
|
|
21
22
|
children,
|
|
22
23
|
...rest
|
|
@@ -25,10 +26,20 @@
|
|
|
25
26
|
size?: Responsive<Size>;
|
|
26
27
|
/** Show the top separator (default true). */
|
|
27
28
|
separator?: boolean;
|
|
29
|
+
/** Horizontal placement of the footer content (action buttons). Default `"right"` — footers
|
|
30
|
+
* right-align actions. Convenience over `class`; a `class` justify-* still overrides (applied last). */
|
|
31
|
+
align?: "left" | "center" | "right" | "between";
|
|
28
32
|
class?: string;
|
|
29
33
|
children?: Snippet;
|
|
30
34
|
} & Omit<HTMLAttributes<HTMLDivElement>, "class"> = $props();
|
|
31
35
|
|
|
36
|
+
const justifyClass: Record<NonNullable<typeof align>, string> = {
|
|
37
|
+
left: "justify-start",
|
|
38
|
+
center: "justify-center",
|
|
39
|
+
right: "justify-end",
|
|
40
|
+
between: "justify-between",
|
|
41
|
+
};
|
|
42
|
+
|
|
32
43
|
// The body→footer gap (`pad`) is ALWAYS applied, so `separator={false}` still leaves breathing room
|
|
33
44
|
// above the footer (just no line). `separator={true}` adds the line + a matching margin above it
|
|
34
45
|
// (`sepGap`), giving the margin → line → pad rhythm.
|
|
@@ -44,7 +55,7 @@
|
|
|
44
55
|
</script>
|
|
45
56
|
|
|
46
57
|
<div
|
|
47
|
-
class="flex items-center
|
|
58
|
+
class="flex items-center {justifyClass[align]} gap-3 {responsiveClasses(size, pad)} {separator
|
|
48
59
|
? 'border-t ' + responsiveClasses(size, sepGap)
|
|
49
60
|
: ''} {cls}"
|
|
50
61
|
style={separator ? `border-color: ${sepColor}` : ""}
|
|
@@ -8,6 +8,9 @@ type $$ComponentProps = {
|
|
|
8
8
|
size?: Responsive<Size>;
|
|
9
9
|
/** Show the top separator (default true). */
|
|
10
10
|
separator?: boolean;
|
|
11
|
+
/** Horizontal placement of the footer content (action buttons). Default `"right"` — footers
|
|
12
|
+
* right-align actions. Convenience over `class`; a `class` justify-* still overrides (applied last). */
|
|
13
|
+
align?: "left" | "center" | "right" | "between";
|
|
11
14
|
class?: string;
|
|
12
15
|
children?: Snippet;
|
|
13
16
|
} & Omit<HTMLAttributes<HTMLDivElement>, "class">;
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
import type { Size } from "../types/sizes.js";
|
|
6
6
|
import type { Responsive } from "../types/responsive.js";
|
|
7
7
|
import type { Variant } from "../types/variants.js";
|
|
8
|
+
import type { FieldChromeProps } from "./field-chrome.js";
|
|
8
9
|
|
|
9
|
-
interface Props extends Omit<HTMLInputAttributes, "type" | "size"
|
|
10
|
+
interface Props extends Omit<HTMLInputAttributes, "type" | "size">, FieldChromeProps {
|
|
10
11
|
value: string;
|
|
11
12
|
class?: string;
|
|
12
13
|
inputClass?: string;
|
|
@@ -2,7 +2,8 @@ import type { HTMLInputAttributes } from "svelte/elements";
|
|
|
2
2
|
import type { Size } from "../types/sizes.js";
|
|
3
3
|
import type { Responsive } from "../types/responsive.js";
|
|
4
4
|
import type { Variant } from "../types/variants.js";
|
|
5
|
-
|
|
5
|
+
import type { FieldChromeProps } from "./field-chrome.js";
|
|
6
|
+
interface Props extends Omit<HTMLInputAttributes, "type" | "size">, FieldChromeProps {
|
|
6
7
|
value: string;
|
|
7
8
|
class?: string;
|
|
8
9
|
inputClass?: string;
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
import type { Size } from "../types/sizes.js";
|
|
12
12
|
import type { Responsive } from "../types/responsive.js";
|
|
13
13
|
import type { Variant } from "../types/variants.js";
|
|
14
|
+
import type { FieldChromeProps } from "./field-chrome.js";
|
|
14
15
|
|
|
15
|
-
interface Props extends Omit<HTMLInputAttributes, "type" | "value" | "size"
|
|
16
|
+
interface Props extends Omit<HTMLInputAttributes, "type" | "value" | "size">, FieldChromeProps {
|
|
16
17
|
value: number | null;
|
|
17
18
|
class?: string;
|
|
18
19
|
inputClass?: string;
|
|
@@ -2,7 +2,8 @@ import type { HTMLInputAttributes } from "svelte/elements";
|
|
|
2
2
|
import type { Size } from "../types/sizes.js";
|
|
3
3
|
import type { Responsive } from "../types/responsive.js";
|
|
4
4
|
import type { Variant } from "../types/variants.js";
|
|
5
|
-
|
|
5
|
+
import type { FieldChromeProps } from "./field-chrome.js";
|
|
6
|
+
interface Props extends Omit<HTMLInputAttributes, "type" | "value" | "size">, FieldChromeProps {
|
|
6
7
|
value: number | null;
|
|
7
8
|
class?: string;
|
|
8
9
|
inputClass?: string;
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
import type { Size } from "../types/sizes.js";
|
|
7
7
|
import type { Responsive } from "../types/responsive.js";
|
|
8
8
|
import type { Variant } from "../types/variants.js";
|
|
9
|
+
import type { FieldChromeProps } from "./field-chrome.js";
|
|
9
10
|
|
|
10
|
-
interface Props extends Omit<HTMLInputAttributes, "type" | "size"
|
|
11
|
+
interface Props extends Omit<HTMLInputAttributes, "type" | "size">, FieldChromeProps {
|
|
11
12
|
value: string;
|
|
12
13
|
class?: string;
|
|
13
14
|
inputClass?: string;
|
|
@@ -2,7 +2,8 @@ import type { HTMLInputAttributes } from "svelte/elements";
|
|
|
2
2
|
import type { Size } from "../types/sizes.js";
|
|
3
3
|
import type { Responsive } from "../types/responsive.js";
|
|
4
4
|
import type { Variant } from "../types/variants.js";
|
|
5
|
-
|
|
5
|
+
import type { FieldChromeProps } from "./field-chrome.js";
|
|
6
|
+
interface Props extends Omit<HTMLInputAttributes, "type" | "size">, FieldChromeProps {
|
|
6
7
|
value: string;
|
|
7
8
|
class?: string;
|
|
8
9
|
inputClass?: string;
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
import type { Size } from "../types/sizes.js";
|
|
7
7
|
import type { Responsive } from "../types/responsive.js";
|
|
8
8
|
import type { Variant } from "../types/variants.js";
|
|
9
|
+
import type { FieldChromeProps } from "./field-chrome.js";
|
|
9
10
|
|
|
10
|
-
interface Props extends Omit<HTMLInputAttributes, "type" | "size"
|
|
11
|
+
interface Props extends Omit<HTMLInputAttributes, "type" | "size">, FieldChromeProps {
|
|
11
12
|
value: string;
|
|
12
13
|
class?: string;
|
|
13
14
|
inputClass?: string;
|
|
@@ -2,7 +2,8 @@ import type { HTMLInputAttributes } from "svelte/elements";
|
|
|
2
2
|
import type { Size } from "../types/sizes.js";
|
|
3
3
|
import type { Responsive } from "../types/responsive.js";
|
|
4
4
|
import type { Variant } from "../types/variants.js";
|
|
5
|
-
|
|
5
|
+
import type { FieldChromeProps } from "./field-chrome.js";
|
|
6
|
+
interface Props extends Omit<HTMLInputAttributes, "type" | "size">, FieldChromeProps {
|
|
6
7
|
value: string;
|
|
7
8
|
class?: string;
|
|
8
9
|
inputClass?: string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
/**
|
|
3
|
+
* The shared **FieldChrome** vocabulary (`label` / `aside` / `error` / `description`) that `Input`,
|
|
4
|
+
* `TextArea`, and the specialized inputs (`PasswordInput` / `EmailInput` / `NumberInput` /
|
|
5
|
+
* `SearchInput`) all render through `FieldChrome`. See `FieldChrome.spec.md`.
|
|
6
|
+
*
|
|
7
|
+
* The specialized inputs forward `{...restProps}` into `<Input>` at runtime, so these props already
|
|
8
|
+
* WORK on them — they just weren't TYPED (their `Props` derived from `HTMLInputAttributes` alone,
|
|
9
|
+
* which has no `label`/`aside`/`error`/`description`). Extending this interface types them without any
|
|
10
|
+
* runtime change. `required`/`id` are NOT here — they are genuine `HTMLInputAttributes` and come from
|
|
11
|
+
* the base. Keep in sync with the chrome props declared on `Input`/`TextArea`.
|
|
12
|
+
*/
|
|
13
|
+
export interface FieldChromeProps {
|
|
14
|
+
/** Renders above the control; `null`/omitted → no label row. */
|
|
15
|
+
label?: string | null;
|
|
16
|
+
/** Right-aligned snippet in the label row. */
|
|
17
|
+
aside?: Snippet;
|
|
18
|
+
/** Inline error row (string → `{@html}`); also drives the shared error state (border + aria-invalid). */
|
|
19
|
+
error?: string | Snippet | null;
|
|
20
|
+
/** Muted help row below the control (string → `{@html}`). */
|
|
21
|
+
description?: string | Snippet | null;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/docs/components.md
CHANGED
|
@@ -590,7 +590,11 @@ Status indicator / label.
|
|
|
590
590
|
- **Location**: `src/lib/components/Badge/Badge.svelte`
|
|
591
591
|
- **Axes**: `size`
|
|
592
592
|
- **Variants**: `default`, `primary`, `success`, `warning`, `danger`, `info`
|
|
593
|
-
- **Props**: `text`, `variant`, `size`, `dismissible`, `rounded`, `children`; dispatches `dismiss`
|
|
593
|
+
- **Props**: `text`, `variant`, `size`, `dismissible`, `rounded`, `href`, `children`; dispatches `dismiss`
|
|
594
|
+
- **Attribute passthrough**: leftover HTML attributes — `class` (merged, appended last), `data-*`
|
|
595
|
+
(e.g. a `data-testid` e2e hook), `aria-*`, `id`, `title`, event handlers — spread onto the chip's
|
|
596
|
+
root element. **`style` is not** passed through (the chip computes its own themed `style`); use
|
|
597
|
+
`class` for style overrides.
|
|
594
598
|
|
|
595
599
|
### NotesEditor
|
|
596
600
|
|