contain-css-svelte 1.1.20 → 1.2.0
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/Card.svelte +15 -6
- package/dist/Card.svelte.d.ts +4 -5
- package/dist/controls/Button.svelte +19 -5
- package/dist/controls/Button.svelte.d.ts +4 -4
- package/dist/controls/ButtonLink.svelte +17 -14
- package/dist/controls/ButtonLink.svelte.d.ts +4 -4
- package/dist/controls/Checkbox.svelte +15 -8
- package/dist/controls/Checkbox.svelte.d.ts +4 -4
- package/dist/controls/CircleButton.svelte +14 -7
- package/dist/controls/CircleButton.svelte.d.ts +4 -4
- package/dist/controls/Input.svelte +14 -3
- package/dist/controls/Input.svelte.d.ts +4 -3
- package/dist/controls/Option.svelte +4 -3
- package/dist/controls/Option.svelte.d.ts +3 -2
- package/dist/controls/RadioButton.svelte +14 -7
- package/dist/controls/RadioButton.svelte.d.ts +4 -4
- package/dist/controls/Select.svelte +15 -3
- package/dist/controls/Select.svelte.d.ts +4 -3
- package/dist/controls/Slider.svelte +5 -11
- package/dist/controls/Slider.svelte.d.ts +3 -3
- package/dist/controls/TabItem.svelte +24 -5
- package/dist/controls/TabItem.svelte.d.ts +4 -4
- package/dist/controls/Toggle.svelte +21 -5
- package/dist/controls/Toggle.svelte.d.ts +4 -4
- package/dist/dropdowns/DropdownMenu.svelte +18 -6
- package/dist/dropdowns/DropdownMenu.svelte.d.ts +4 -4
- package/dist/layout/Accordion.svelte +17 -2
- package/dist/layout/Accordion.svelte.d.ts +5 -3
- package/dist/layout/Bar.svelte +13 -7
- package/dist/layout/Bar.svelte.d.ts +4 -4
- package/dist/layout/Column.svelte.d.ts +3 -3
- package/dist/layout/ColumnContainer.svelte +12 -9
- package/dist/layout/ColumnContainer.svelte.d.ts +4 -4
- package/dist/layout/Columns.svelte +4 -3
- package/dist/layout/Columns.svelte.d.ts +7 -3
- package/dist/layout/Container.svelte +23 -8
- package/dist/layout/Container.svelte.d.ts +7 -5
- package/dist/layout/DataList.svelte +15 -7
- package/dist/layout/DataList.svelte.d.ts +5 -4
- package/dist/layout/DataListItem.svelte +14 -8
- package/dist/layout/DataListItem.svelte.d.ts +4 -4
- package/dist/layout/Fieldset.svelte +16 -8
- package/dist/layout/Fieldset.svelte.d.ts +6 -3
- package/dist/layout/Form.svelte +17 -8
- package/dist/layout/Form.svelte.d.ts +8 -6
- package/dist/layout/FormItem.svelte +12 -7
- package/dist/layout/FormItem.svelte.d.ts +4 -3
- package/dist/layout/FormProvider.svelte +3 -0
- package/dist/layout/GridLayout.svelte +14 -9
- package/dist/layout/GridLayout.svelte.d.ts +4 -4
- package/dist/layout/GridRow.svelte +6 -10
- package/dist/layout/GridRow.svelte.d.ts +3 -2
- package/dist/layout/Hero.svelte +14 -8
- package/dist/layout/Hero.svelte.d.ts +4 -4
- package/dist/layout/Inline.svelte +16 -15
- package/dist/layout/Inline.svelte.d.ts +4 -4
- package/dist/layout/MenuList.svelte +13 -6
- package/dist/layout/MenuList.svelte.d.ts +4 -4
- package/dist/layout/Page.svelte +14 -8
- package/dist/layout/Page.svelte.d.ts +11 -3
- package/dist/layout/ResponsiveText.svelte +4 -0
- package/dist/layout/Row.svelte.d.ts +3 -3
- package/dist/layout/RowContainer.svelte +12 -9
- package/dist/layout/RowContainer.svelte.d.ts +4 -4
- package/dist/layout/Sidebar.svelte +17 -6
- package/dist/layout/Sidebar.svelte.d.ts +12 -4
- package/dist/layout/SplitPane.svelte +8 -14
- package/dist/layout/SplitPane.svelte.d.ts +16 -2
- package/dist/layout/Stack.svelte +16 -15
- package/dist/layout/Stack.svelte.d.ts +4 -4
- package/dist/layout/TabBar.svelte +12 -2
- package/dist/layout/TabBar.svelte.d.ts +17 -10
- package/dist/layout/Table.svelte +5 -1
- package/dist/layout/Tile.svelte +40 -27
- package/dist/layout/Tile.svelte.d.ts +32 -10
- package/dist/misc/Code.svelte +2 -0
- package/dist/misc/Progress.svelte +25 -8
- package/dist/misc/Progress.svelte.d.ts +15 -8
- package/dist/misc/Tag.svelte +97 -44
- package/dist/misc/Tag.svelte.d.ts +17 -5
- package/dist/overlays/Dialog.svelte +18 -5
- package/dist/overlays/Dialog.svelte.d.ts +5 -3
- package/dist/overlays/Tooltip.svelte +21 -3
- package/dist/overlays/Tooltip.svelte.d.ts +5 -3
- package/dist/styleProps.d.ts +67 -0
- package/dist/styleProps.js +76 -0
- package/dist/types.d.ts +40 -1
- package/dist/types.js +1 -1
- package/dist/typography/Text.svelte +4 -11
- package/dist/typography/TextLayout.svelte +4 -7
- package/dist/typography/TextLayout.svelte.d.ts +4 -3
- package/dist/util.d.ts +60 -3
- package/dist/util.js +101 -11
- package/package.json +1 -1
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
-
type
|
|
3
|
+
import type { ContainProps } from "../types";
|
|
4
|
+
type Props = ContainProps<HTMLAttributes<HTMLElement>, {
|
|
4
5
|
left?: Snippet;
|
|
5
6
|
right?: Snippet;
|
|
6
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Accessible name for the drag handle between the panes. Name what the
|
|
9
|
+
* panes hold -- `resizerLabel="Resize the preview"` -- so it is clear
|
|
10
|
+
* what moving the handle does.
|
|
11
|
+
*/
|
|
12
|
+
resizerLabel?: string;
|
|
13
|
+
}, {
|
|
14
|
+
bg?: string | null;
|
|
15
|
+
fg?: string | null;
|
|
16
|
+
border?: string | null;
|
|
17
|
+
height?: string | null;
|
|
18
|
+
leftWidth?: string | null;
|
|
19
|
+
rightWidth?: string | null;
|
|
20
|
+
}>;
|
|
7
21
|
declare const SplitPane: import("svelte").Component<Props, {}, "">;
|
|
8
22
|
type SplitPane = ReturnType<typeof SplitPane>;
|
|
9
23
|
export default SplitPane;
|
package/dist/layout/Stack.svelte
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
<script lang="ts">import {
|
|
2
|
-
|
|
1
|
+
<script lang="ts">import { elementProps } from "../util";
|
|
2
|
+
import { MARGIN_VARS, PADDING_VARS, RADIUS_VARS, } from "../styleProps";
|
|
3
|
+
let { fill = false, stretch = false, split = false, center = false, justify = null, align = null, gap = null, children, class: className, ...restProps } = $props();
|
|
3
4
|
const resolvedAlign = $derived(align ?? (center ? "center" : null));
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
/* The shorthands stack's own CSS backs, one group per mixin it
|
|
6
|
+
includes. The Props type is derived from this same array, so what the
|
|
7
|
+
component accepts and what it emits cannot drift apart. */
|
|
8
|
+
const STACK_VARS = [
|
|
9
|
+
...PADDING_VARS,
|
|
10
|
+
...RADIUS_VARS,
|
|
11
|
+
...MARGIN_VARS,
|
|
12
|
+
];
|
|
13
|
+
const el = $derived(elementProps({ justify, align: resolvedAlign, gap, ...restProps }, "stack", [
|
|
14
|
+
...STACK_VARS,
|
|
10
15
|
"bg",
|
|
11
16
|
"fg",
|
|
12
|
-
"padding",
|
|
13
17
|
"width",
|
|
14
18
|
"height",
|
|
15
19
|
"gap",
|
|
16
20
|
"justify",
|
|
17
21
|
"align",
|
|
18
|
-
|
|
19
|
-
"marginInline",
|
|
20
|
-
]) + (inlineStyle ?? ""));
|
|
22
|
+
]));
|
|
21
23
|
</script>
|
|
22
24
|
|
|
23
25
|
<div
|
|
24
|
-
class="stack"
|
|
26
|
+
class={["stack", className]}
|
|
25
27
|
class:fill
|
|
26
28
|
class:stretch
|
|
27
29
|
class:split
|
|
28
|
-
{
|
|
29
|
-
{...elementProps}
|
|
30
|
+
{...el}
|
|
30
31
|
>
|
|
31
32
|
{@render children?.()}
|
|
32
33
|
</div>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
-
import type { BaseStyleProps, MarginStyleProps } from "../types";
|
|
4
|
-
type
|
|
3
|
+
import type { BaseStyleProps, ContainProps, MarginStyleProps } from "../types";
|
|
4
|
+
import { type StyleProps } from "../styleProps";
|
|
5
|
+
declare const Stack: import("svelte").Component<ContainProps<HTMLAttributes<HTMLDivElement>, {
|
|
5
6
|
fill?: boolean;
|
|
6
7
|
stretch?: boolean;
|
|
7
8
|
split?: boolean;
|
|
@@ -10,7 +11,6 @@ type Props = {
|
|
|
10
11
|
align?: string | null;
|
|
11
12
|
gap?: string | null;
|
|
12
13
|
children?: Snippet;
|
|
13
|
-
}
|
|
14
|
-
declare const Stack: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
}, BaseStyleProps & MarginStyleProps & StyleProps<readonly ["padding", "borderRadius", "marginBlock", "marginInline"]>>, {}, "">;
|
|
15
15
|
type Stack = ReturnType<typeof Stack>;
|
|
16
16
|
export default Stack;
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
<script lang="ts">import Bar from "./Bar.svelte";
|
|
2
2
|
import TabItem from "../controls/TabItem.svelte";
|
|
3
|
-
|
|
3
|
+
import { elementProps } from "../util";
|
|
4
|
+
import { COLOR_VARS, TYPOGRAPHY_VARS, } from "../styleProps";
|
|
5
|
+
let { sticky = false, active = $bindable(null), items = [], onchange, children, class: className, ...restProps } = $props();
|
|
6
|
+
/* The shorthands this component's own CSS backs, one group per mixin
|
|
7
|
+
it includes. The Props type is derived from this same array, so what
|
|
8
|
+
the component accepts and what it emits cannot drift apart. */
|
|
9
|
+
const TAB_BAR_VARS = [
|
|
10
|
+
...COLOR_VARS,
|
|
11
|
+
...TYPOGRAPHY_VARS,
|
|
12
|
+
];
|
|
13
|
+
const el = $derived(elementProps(restProps, "tab-bar", TAB_BAR_VARS));
|
|
4
14
|
let lastActive = $state(active);
|
|
5
15
|
</script>
|
|
6
16
|
|
|
7
|
-
<div class="tabs" class:sticky>
|
|
17
|
+
<div class={["tabs", className]} class:sticky {...el}>
|
|
8
18
|
<Bar
|
|
9
19
|
padding="0"
|
|
10
20
|
--button-height="var(--tab-bar-height, 3em)"
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
1
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
2
|
+
import type { ContainProps } from "../types";
|
|
3
|
+
import { type StyleProps } from "../styleProps";
|
|
4
|
+
declare const TabBar: import("svelte").Component<ContainProps<HTMLAttributes<HTMLDivElement>, {
|
|
6
5
|
sticky?: boolean;
|
|
7
|
-
active?: string |
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
active?: string | {
|
|
7
|
+
label: string;
|
|
8
|
+
value: string;
|
|
9
|
+
} | null;
|
|
10
|
+
items?: (string | {
|
|
11
|
+
label: string;
|
|
12
|
+
value: string;
|
|
13
|
+
})[];
|
|
14
|
+
onchange?: (value: string | {
|
|
15
|
+
label: string;
|
|
16
|
+
value: string;
|
|
17
|
+
} | null) => void;
|
|
10
18
|
children?: import("svelte").Snippet;
|
|
11
|
-
}
|
|
12
|
-
declare const TabBar: import("svelte").Component<Props, {}, "active">;
|
|
19
|
+
}, StyleProps<readonly ["bg", "fg", "fontFamily", "fontSize", "fontWeight", "lineHeight", "letterSpacing", "textAlign", "textTransform", "textDecoration", "fontVariant"]>>, {}, "active">;
|
|
13
20
|
type TabBar = ReturnType<typeof TabBar>;
|
|
14
21
|
export default TabBar;
|
package/dist/layout/Table.svelte
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
<script lang="ts"
|
|
1
|
+
<script lang="ts">/* No attribute pass-through, deliberately: the sticky variant renders the
|
|
2
|
+
visible tables AND a visually-hidden clone of them used to measure column
|
|
3
|
+
widths. Spreading a caller's `id` would emit it twice, which is invalid.
|
|
4
|
+
Set attributes on the <table> markup you pass in as `thead`/`tbody`. */
|
|
5
|
+
let { sticky = false, column_widths = null, thead, tbody, children, } = $props();
|
|
2
6
|
// svelte-ignore state_referenced_locally
|
|
3
7
|
let columns = $state(column_widths || []);
|
|
4
8
|
/* Code for syncing column widths for scrolling table solution */
|
package/dist/layout/Tile.svelte
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
<script lang="ts">import {
|
|
1
|
+
<script lang="ts">import { splitProps } from "../util";
|
|
2
|
+
import { COLOR_VARS, PADDING_VARS, RADIUS_VARS, MARGIN_VARS, TYPOGRAPHY_CONTAINER_VARS, } from "../styleProps";
|
|
3
|
+
/* The shorthands this component's own CSS backs, one group per mixin
|
|
4
|
+
it includes. The Props type is derived from this same array, so what
|
|
5
|
+
the component accepts and what it emits cannot drift apart. */
|
|
6
|
+
const TILE_VARS = [
|
|
7
|
+
...COLOR_VARS,
|
|
8
|
+
...PADDING_VARS,
|
|
9
|
+
...RADIUS_VARS,
|
|
10
|
+
...MARGIN_VARS,
|
|
11
|
+
...TYPOGRAPHY_CONTAINER_VARS,
|
|
12
|
+
];
|
|
2
13
|
let { checked = $bindable(false), ...props } = $props();
|
|
3
14
|
/* Props to CSS variables, the way Stack, Card, Tag and the rest do it, so a
|
|
4
15
|
Tile can be aimed with `<Tile center>` rather than only a raw variable. */
|
|
@@ -16,43 +27,45 @@ const styleProps = $derived.by(() => {
|
|
|
16
27
|
align: align ?? (center ? "center" : null),
|
|
17
28
|
};
|
|
18
29
|
});
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
function getSelectableInputProps(value) {
|
|
36
|
-
return stripOwnProps(value);
|
|
37
|
-
}
|
|
38
|
-
function getInteractiveButtonProps(value) {
|
|
39
|
-
return stripOwnProps(value);
|
|
40
|
-
}
|
|
30
|
+
/* splitProps consumes the style props and `--*`, and keeps `style` out of
|
|
31
|
+
the attributes; the props that are Tile's own rather than the element's
|
|
32
|
+
are peeled off here first. In the selectable case the variables land on
|
|
33
|
+
the label that `.tile` styles while the attributes go to the checkbox,
|
|
34
|
+
which is what a caller's `aria-*` and `data-*` are describing. */
|
|
35
|
+
const el = $derived.by(() => {
|
|
36
|
+
const { selectable: _selectable, interactive: _interactive, children: _children, center: _center, class: _class, ...rest } = props;
|
|
37
|
+
return splitProps({ ...rest, ...styleProps }, "tile", [
|
|
38
|
+
...TILE_VARS,
|
|
39
|
+
"width",
|
|
40
|
+
"height",
|
|
41
|
+
"justify",
|
|
42
|
+
"align",
|
|
43
|
+
]);
|
|
44
|
+
});
|
|
45
|
+
const className = $derived(props.class);
|
|
41
46
|
</script>
|
|
42
47
|
|
|
43
48
|
{#if props.selectable}
|
|
44
|
-
<label class="tile" {style}>
|
|
49
|
+
<label class={["tile", className]} style={el.style}>
|
|
45
50
|
<div class="checkbox">
|
|
46
|
-
<input
|
|
51
|
+
<input
|
|
52
|
+
type="checkbox"
|
|
53
|
+
bind:checked
|
|
54
|
+
{...el.attrs as HTMLInputAttributes}
|
|
55
|
+
/>
|
|
47
56
|
</div>
|
|
48
57
|
{@render props.children?.()}
|
|
49
58
|
</label>
|
|
50
59
|
{:else if props.interactive}
|
|
51
|
-
<button
|
|
60
|
+
<button
|
|
61
|
+
class={["tile", className]}
|
|
62
|
+
style={el.style}
|
|
63
|
+
{...el.attrs as HTMLButtonAttributes}
|
|
64
|
+
>
|
|
52
65
|
{@render props.children?.()}
|
|
53
66
|
</button>
|
|
54
67
|
{:else}
|
|
55
|
-
<div class="tile" {style} {...
|
|
68
|
+
<div class={["tile", className]} style={el.style} {...el.attrs}>
|
|
56
69
|
{@render props.children?.()}
|
|
57
70
|
</div>
|
|
58
71
|
{/if}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
2
|
import type { HTMLAttributes, HTMLButtonAttributes, HTMLInputAttributes } from "svelte/elements";
|
|
3
|
+
import { type StyleProps } from "../styleProps";
|
|
3
4
|
import type { BaseStyleProps, MarginStyleProps } from "../types";
|
|
4
|
-
|
|
5
|
+
declare const Tile: import("svelte").Component<(BaseStyleProps & MarginStyleProps & StyleProps<readonly ["bg", "fg", "padding", "borderRadius", "marginBlock", "marginInline", "fontFamily", "fontSize", "fontWeight", "lineHeight", "letterSpacing", "textAlign", "textTransform", "textDecoration", "fontVariant", "lineWidth"]> & {
|
|
5
6
|
/** Distribution along the tile's own axis, which is vertical. */
|
|
6
7
|
justify?: string | null;
|
|
7
8
|
/** Cross-axis alignment, which is horizontal. Centred already. */
|
|
@@ -14,23 +15,44 @@ type BaseProps = BaseStyleProps & MarginStyleProps & {
|
|
|
14
15
|
*/
|
|
15
16
|
center?: boolean;
|
|
16
17
|
children?: Snippet;
|
|
17
|
-
}
|
|
18
|
-
type StaticTileProps = BaseProps & HTMLAttributes<HTMLDivElement> & {
|
|
18
|
+
} & HTMLAttributes<HTMLDivElement> & {
|
|
19
19
|
interactive?: false;
|
|
20
20
|
selectable?: false;
|
|
21
21
|
checked?: never;
|
|
22
|
-
}
|
|
23
|
-
|
|
22
|
+
}) | (BaseStyleProps & MarginStyleProps & StyleProps<readonly ["bg", "fg", "padding", "borderRadius", "marginBlock", "marginInline", "fontFamily", "fontSize", "fontWeight", "lineHeight", "letterSpacing", "textAlign", "textTransform", "textDecoration", "fontVariant", "lineWidth"]> & {
|
|
23
|
+
/** Distribution along the tile's own axis, which is vertical. */
|
|
24
|
+
justify?: string | null;
|
|
25
|
+
/** Cross-axis alignment, which is horizontal. Centred already. */
|
|
26
|
+
align?: string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Shorthand for centring the tile's contents. Sets both axes, unlike
|
|
29
|
+
* `Stack`'s `center`, because a Tile already centres horizontally -- setting
|
|
30
|
+
* only the cross axis here would be a no-op and `<Tile center>` would look
|
|
31
|
+
* broken.
|
|
32
|
+
*/
|
|
33
|
+
center?: boolean;
|
|
34
|
+
children?: Snippet;
|
|
35
|
+
} & HTMLButtonAttributes & {
|
|
24
36
|
interactive: true;
|
|
25
37
|
selectable?: false;
|
|
26
38
|
checked?: never;
|
|
27
|
-
}
|
|
28
|
-
|
|
39
|
+
}) | (BaseStyleProps & MarginStyleProps & StyleProps<readonly ["bg", "fg", "padding", "borderRadius", "marginBlock", "marginInline", "fontFamily", "fontSize", "fontWeight", "lineHeight", "letterSpacing", "textAlign", "textTransform", "textDecoration", "fontVariant", "lineWidth"]> & {
|
|
40
|
+
/** Distribution along the tile's own axis, which is vertical. */
|
|
41
|
+
justify?: string | null;
|
|
42
|
+
/** Cross-axis alignment, which is horizontal. Centred already. */
|
|
43
|
+
align?: string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Shorthand for centring the tile's contents. Sets both axes, unlike
|
|
46
|
+
* `Stack`'s `center`, because a Tile already centres horizontally -- setting
|
|
47
|
+
* only the cross axis here would be a no-op and `<Tile center>` would look
|
|
48
|
+
* broken.
|
|
49
|
+
*/
|
|
50
|
+
center?: boolean;
|
|
51
|
+
children?: Snippet;
|
|
52
|
+
} & HTMLInputAttributes & {
|
|
29
53
|
selectable: true;
|
|
30
54
|
interactive?: false;
|
|
31
55
|
checked?: boolean;
|
|
32
|
-
}
|
|
33
|
-
type Props = StaticTileProps | InteractiveTileProps | SelectableTileProps;
|
|
34
|
-
declare const Tile: import("svelte").Component<Props, {}, "checked">;
|
|
56
|
+
}), {}, "checked">;
|
|
35
57
|
type Tile = ReturnType<typeof Tile>;
|
|
36
58
|
export default Tile;
|
package/dist/misc/Code.svelte
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">const browser = typeof window !== "undefined";
|
|
2
|
+
/* No attribute pass-through, deliberately: this renders CodeInner (loaded
|
|
3
|
+
lazily in the browser) and no element of its own. */
|
|
2
4
|
let { code, inline = false, language = "html" } = $props();
|
|
3
5
|
let component = $state(null);
|
|
4
6
|
if (browser) {
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
<script lang="ts">import {
|
|
2
|
-
|
|
3
|
-
let { state = "inprogress", value = 0, max = 100, bg = null, fg = null, padding = null, width = null, height = null, children, ...restProps } = $props();
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
<script lang="ts">import { elementProps } from "../util";
|
|
2
|
+
import { COLOR_VARS, PADDING_VARS, RADIUS_VARS, TYPOGRAPHY_CONTAINER_VARS, } from "../styleProps";
|
|
3
|
+
let { state = "inprogress", value = 0, max = 100, bg = null, fg = null, padding = null, width = null, height = null, children, progressLabel = "Progress", class: className, ...restProps } = $props();
|
|
4
|
+
/* The shorthands this component's own CSS backs, one group per mixin
|
|
5
|
+
it includes. The Props type is derived from this same array, so what
|
|
6
|
+
the component accepts and what it emits cannot drift apart. */
|
|
7
|
+
const PROGRESS_VARS = [
|
|
8
|
+
...COLOR_VARS,
|
|
9
|
+
...PADDING_VARS,
|
|
10
|
+
...RADIUS_VARS,
|
|
11
|
+
...TYPOGRAPHY_CONTAINER_VARS,
|
|
12
|
+
];
|
|
13
|
+
const cssKeys = [...PROGRESS_VARS, "width", "height"];
|
|
14
|
+
/* Every style prop is destructured above, so they are handed back
|
|
15
|
+
explicitly. Passing `restProps` alone -- which is what this did before --
|
|
16
|
+
meant <Progress bg="red"> emitted no --progress-bg at all. */
|
|
17
|
+
const el = $derived(elementProps({ bg, fg, padding, width, height, ...restProps }, "progress", cssKeys));
|
|
6
18
|
// Compute filled fraction (0..1). 'indeterminate' treats as 1 for the visual bar,
|
|
7
19
|
// but the native <progress> should omit the value attribute for indeterminate.
|
|
8
20
|
let fillFraction = $derived(value === "indeterminate"
|
|
@@ -19,11 +31,16 @@ let halfFull = $derived(fillFraction > 0.5);
|
|
|
19
31
|
1) Hidden native <progress> for a11y.
|
|
20
32
|
If 'indeterminate', omit the value attribute entirely.
|
|
21
33
|
-->
|
|
22
|
-
<div class="progress-container" data-state={state} {
|
|
34
|
+
<div class={["progress-container", className]} data-state={state} {...el}>
|
|
23
35
|
{#if value === "indeterminate"}
|
|
24
|
-
<progress aria-label=
|
|
36
|
+
<progress aria-label={progressLabel} {max} hidden></progress>
|
|
25
37
|
{:else}
|
|
26
|
-
<progress
|
|
38
|
+
<progress
|
|
39
|
+
aria-label={progressLabel}
|
|
40
|
+
{max}
|
|
41
|
+
value={Number(value)}
|
|
42
|
+
hidden
|
|
43
|
+
></progress>
|
|
27
44
|
{/if}
|
|
28
45
|
|
|
29
46
|
<!-- 2) Custom track with diagonal stripes (scrolling) when animateTrack=true -->
|
|
@@ -1,15 +1,22 @@
|
|
|
1
|
+
import { type StyleProps } from "../styleProps";
|
|
1
2
|
import type { Snippet } from "svelte";
|
|
2
|
-
type
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
import type { BaseStyleProps, ContainProps } from "../types";
|
|
5
|
+
declare const Progress: import("svelte").Component<ContainProps<HTMLAttributes<HTMLDivElement>, {
|
|
3
6
|
state?: "uninitiated" | "inprogress" | "complete";
|
|
4
7
|
value?: number | "indeterminate";
|
|
5
8
|
max?: number;
|
|
6
|
-
bg?: string | null;
|
|
7
|
-
fg?: string | null;
|
|
8
|
-
padding?: string | null;
|
|
9
|
-
width?: string | null;
|
|
10
|
-
height?: string | null;
|
|
11
9
|
children?: Snippet;
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Accessible name for the native <progress> that carries this bar's
|
|
12
|
+
* semantics. Say what is progressing -- `progressLabel="Upload"` -- since
|
|
13
|
+
* "Progress" tells a screen-reader user nothing they did not already know
|
|
14
|
+
* from the role.
|
|
15
|
+
*
|
|
16
|
+
* Named `progressLabel`, not `label`, because `label` is a real HTML
|
|
17
|
+
* attribute; a style or a11y prop must never shadow one.
|
|
18
|
+
*/
|
|
19
|
+
progressLabel?: string;
|
|
20
|
+
}, BaseStyleProps & StyleProps<readonly ["bg", "fg", "padding", "borderRadius", "fontFamily", "fontSize", "fontWeight", "lineHeight", "letterSpacing", "textAlign", "textTransform", "textDecoration", "fontVariant", "lineWidth"]>>, {}, "">;
|
|
14
21
|
type Progress = ReturnType<typeof Progress>;
|
|
15
22
|
export default Progress;
|
package/dist/misc/Tag.svelte
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
<script lang="ts">import {
|
|
2
|
-
|
|
3
|
-
let
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
<script lang="ts">import { elementProps } from "../util";
|
|
2
|
+
import { COLOR_VARS, PADDING_VARS, RADIUS_VARS, TYPOGRAPHY_VARS, } from "../styleProps";
|
|
3
|
+
let { children, primary, warning, danger, success, info, onclose = null, closeLabel = "Remove", class: className, ...restProps } = $props();
|
|
4
|
+
/* The shorthands tag's own CSS backs, one group per mixin it
|
|
5
|
+
includes. The Props type is derived from this same array, so what the
|
|
6
|
+
component accepts and what it emits cannot drift apart. */
|
|
7
|
+
const TAG_VARS = [
|
|
8
|
+
...COLOR_VARS,
|
|
9
|
+
...PADDING_VARS,
|
|
10
|
+
...RADIUS_VARS,
|
|
11
|
+
...TYPOGRAPHY_VARS,
|
|
12
|
+
];
|
|
13
|
+
const el = $derived(elementProps(restProps, "tag", TAG_VARS));
|
|
10
14
|
</script>
|
|
11
15
|
|
|
12
16
|
<span
|
|
13
|
-
{
|
|
14
|
-
class="tag"
|
|
17
|
+
class={["tag", className]}
|
|
15
18
|
class:closable={!!onclose}
|
|
16
|
-
{...restProps}
|
|
17
19
|
class:primary
|
|
18
20
|
class:warning
|
|
19
21
|
class:danger
|
|
20
22
|
class:success
|
|
21
23
|
class:info
|
|
24
|
+
{...el}
|
|
22
25
|
>
|
|
23
|
-
{@render children?.()}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
</button>
|
|
29
|
-
{/if}
|
|
26
|
+
{@render children?.()}{#if onclose}<button
|
|
27
|
+
class="close-button"
|
|
28
|
+
aria-label={closeLabel}
|
|
29
|
+
onclick={onclose}><span aria-hidden="true">×</span></button
|
|
30
|
+
>{/if}
|
|
30
31
|
</span>
|
|
31
32
|
|
|
32
33
|
<style>/* Logical, not top/bottom/left/right: margin-block/margin-inline already take
|
|
@@ -161,48 +162,100 @@ let style = $derived(injectVars(restProps, "tag", [
|
|
|
161
162
|
margin-inline-end: var(--space);
|
|
162
163
|
}
|
|
163
164
|
|
|
165
|
+
/* A closable tag lays its label and button out in flow rather than absolutely
|
|
166
|
+
positioning the button over the top-right corner. The old approach needed a
|
|
167
|
+
literal in the markup to stop the button covering the last character,
|
|
168
|
+
which still overlapped once a tag wrapped to two lines and put the button's
|
|
169
|
+
hit area outside the padding. As a flex item the button reserves its own
|
|
170
|
+
space at any length, and the gap scales with the tag's font-size. */
|
|
164
171
|
.tag.closable {
|
|
165
|
-
|
|
172
|
+
display: inline-flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
gap: var(--tag-close-button-gap, 0.35em);
|
|
166
175
|
}
|
|
167
176
|
|
|
168
|
-
.tag button {
|
|
177
|
+
.tag .close-button {
|
|
169
178
|
background: transparent;
|
|
170
179
|
color: inherit;
|
|
171
180
|
box-shadow: none;
|
|
172
181
|
border: none;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
182
|
+
padding: 0;
|
|
183
|
+
margin: 0;
|
|
184
|
+
/* Square, so the focus ring and pointer target read as a button rather
|
|
185
|
+
than tracking the width of the glyph. */
|
|
186
|
+
inline-size: var(--tag-close-button-size, 1.25em);
|
|
187
|
+
block-size: var(--tag-close-button-size, 1.25em);
|
|
188
|
+
position: relative;
|
|
189
|
+
display: inline-flex;
|
|
190
|
+
align-items: center;
|
|
191
|
+
justify-content: center;
|
|
192
|
+
border-radius: var(--tag-close-button-border-radius, 50%);
|
|
193
|
+
font-size: inherit;
|
|
194
|
+
line-height: 1;
|
|
195
|
+
flex: none;
|
|
176
196
|
cursor: var(--tag-close-button-cursor, var(--button-cursor, var(--cursor, pointer)));
|
|
177
197
|
transition: filter var(--tag-close-button-transition, var(--button-transition, var(--transition, 300ms))), background-color var(--tag-close-button-transition, var(--button-transition, var(--transition, 300ms))), border-color var(--tag-close-button-transition, var(--button-transition, var(--transition, 300ms))), box-shadow var(--tag-close-button-transition, var(--button-transition, var(--transition, 300ms))), transform var(--tag-close-button-transition, var(--button-transition, var(--transition, 300ms)));
|
|
178
198
|
}
|
|
179
199
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
200
|
+
/* The affordance is a scrim mixed from the tag's own FOREGROUND, not from
|
|
201
|
+
`clickable()`'s fill.
|
|
202
|
+
|
|
203
|
+
clickable() derives its hover fill from --_background-color, which this
|
|
204
|
+
button inherits from the tag. On a red tag that produced 90% red + 10%
|
|
205
|
+
white -- a muddy circle a shade off the tag it sits on, reading as a
|
|
206
|
+
rendering artifact rather than a control. Mixing from currentColor
|
|
207
|
+
instead inverts correctly against any tag colour: a light scrim on a
|
|
208
|
+
saturated tag, a dark one on the default pale tag, with no per-variant
|
|
209
|
+
rules. */
|
|
210
|
+
.tag .close-button::before {
|
|
211
|
+
content: "";
|
|
212
|
+
position: absolute;
|
|
213
|
+
inset: 0;
|
|
214
|
+
border-radius: inherit;
|
|
215
|
+
background-color: transparent;
|
|
216
|
+
transition: background-color var(--tag-close-button-transition, var(--transition, 150ms));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.tag .close-button:hover::before {
|
|
220
|
+
background-color: var(--tag-close-button-hover-bg, color-mix(in oklab, transparent, currentColor 18%));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.tag .close-button:active::before {
|
|
224
|
+
background-color: var(--tag-close-button-active-bg, color-mix(in oklab, transparent, currentColor 30%));
|
|
185
225
|
}
|
|
186
226
|
|
|
187
|
-
.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
227
|
+
/* WCAG 2.5.8 wants a 24x24 CSS px target. The glyph is sized in `em` so it
|
|
228
|
+
stays proportional to a tag that is deliberately tiny (0.75rem), which
|
|
229
|
+
left a 15x15 target. This expands the POINTER target without changing
|
|
230
|
+
the visual size or the tag's height. */
|
|
231
|
+
.tag .close-button::after {
|
|
232
|
+
content: "";
|
|
233
|
+
position: absolute;
|
|
234
|
+
top: 50%;
|
|
235
|
+
left: 50%;
|
|
236
|
+
translate: -50% -50%;
|
|
237
|
+
inline-size: max(100%, var(--tag-close-button-target-size, 24px));
|
|
238
|
+
block-size: max(100%, var(--tag-close-button-target-size, 24px));
|
|
192
239
|
}
|
|
193
240
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
241
|
+
/* focus-ring()'s 3px spread shadow plus its 2px offset is sized for a button
|
|
242
|
+
standing on a page; on a 15px control inside a 26px tag it ballooned well
|
|
243
|
+
outside the tag.
|
|
244
|
+
|
|
245
|
+
The room available is exactly the tag's padding-block (0.2em, ~2.4px at
|
|
246
|
+
the default tag font-size) -- the button is as tall as the tag's line box,
|
|
247
|
+
so there is nothing else to grow into. Hence a 2px ring at no offset: it
|
|
248
|
+
reads clearly, hugs the circle, and clears the tag's edge. The scrim stays
|
|
249
|
+
lit under focus so keyboard focus reads the same as pointer hover (the
|
|
250
|
+
`focusable-as-hover` idea, with this component's own fill). */
|
|
251
|
+
.tag .close-button:focus-visible {
|
|
252
|
+
outline: var(--tag-close-button-focus-color, var(--focus-color, currentColor)) solid var(--tag-close-button-focus-width, 2px);
|
|
253
|
+
outline-offset: var(--tag-close-button-focus-offset, 0px);
|
|
254
|
+
box-shadow: none;
|
|
200
255
|
}
|
|
201
256
|
|
|
202
|
-
.tag button:focus-visible {
|
|
203
|
-
|
|
204
|
-
outline-offset: var(--focus-outline-offset, 2px);
|
|
205
|
-
box-shadow: var(--focus-ring-box-shadow, 0 0 0 3px var(--focus-shadow-color, rgba(100, 150, 250, 0.5)));
|
|
257
|
+
.tag .close-button:focus-visible::before {
|
|
258
|
+
background-color: var(--tag-close-button-hover-bg, color-mix(in oklab, transparent, currentColor 18%));
|
|
206
259
|
}
|
|
207
260
|
|
|
208
261
|
.tag:first-child {
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
1
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
2
|
-
import type { TagStyleProps } from "../types";
|
|
3
|
-
type
|
|
4
|
-
|
|
3
|
+
import type { ContainProps, TagStyleProps } from "../types";
|
|
4
|
+
import { type StyleProps } from "../styleProps";
|
|
5
|
+
declare const Tag: import("svelte").Component<ContainProps<HTMLAttributes<HTMLSpanElement>, {
|
|
6
|
+
children?: Snippet;
|
|
5
7
|
primary?: boolean;
|
|
6
8
|
warning?: boolean;
|
|
7
9
|
danger?: boolean;
|
|
8
10
|
success?: boolean;
|
|
9
11
|
info?: boolean;
|
|
10
12
|
onclose?: (() => void) | null;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Accessible name for the close button.
|
|
15
|
+
*
|
|
16
|
+
* The default describes the *widget* ("close a tag"), which is rarely
|
|
17
|
+
* what the action means to a user. A tag is a filter chip in one app and
|
|
18
|
+
* a removable label in another, so say what pressing it does here:
|
|
19
|
+
* `closeLabel="Remove Fiction"`, `closeLabel="Stop searching by author"`.
|
|
20
|
+
* Including the tag's own text is what makes a list of close buttons
|
|
21
|
+
* distinguishable to a screen reader.
|
|
22
|
+
*/
|
|
23
|
+
closeLabel?: string;
|
|
24
|
+
}, TagStyleProps & StyleProps<readonly ["bg", "fg", "padding", "borderRadius", "fontFamily", "fontSize", "fontWeight", "lineHeight", "letterSpacing", "textAlign", "textTransform", "textDecoration", "fontVariant"]>>, {}, "">;
|
|
13
25
|
type Tag = ReturnType<typeof Tag>;
|
|
14
26
|
export default Tag;
|