@threadlabs/looma 0.10.11 → 0.10.12
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/components/ui-list/ui-list.html +33 -0
- package/components/ui-list-item/ui-list-item.html +146 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/styles/ui-list-item.css +146 -0
- package/styles/ui-list.css +33 -0
- package/vanilla/UiList.d.ts +14 -0
- package/vanilla/UiList.js +29 -0
- package/vanilla/UiListItem.d.ts +15 -0
- package/vanilla/UiListItem.js +77 -0
- package/vanilla/index.js +2 -0
- package/vue/UiList.d.ts +18 -0
- package/vue/UiList.js +2 -0
- package/vue/UiList.vue +60 -0
- package/vue/UiListItem.d.ts +26 -0
- package/vue/UiListItem.js +2 -0
- package/vue/UiListItem.vue +171 -0
- package/vue/chunks/UiList.js +24 -0
- package/vue/chunks/UiListItem.js +39 -0
- package/vue/components.css +140 -0
- package/vue/index.d.ts +2 -0
- package/vue/index.js +3 -1
package/package.json
CHANGED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/* Generated by HTML Next 1.0.0-alpha.5. Do not edit. */
|
|
2
|
+
@scope ([data-component~="ui-list-item"]) to ([data-component], [data-slotted]) {
|
|
3
|
+
/* One entry in a list: something to recognise (leading, usually an icon), its name (the default
|
|
4
|
+
slot), one line about it (description), and what it offers (trailing, such as a button or a
|
|
5
|
+
badge). The title and description are one line each and end in an ellipsis, so every item in a
|
|
6
|
+
list has the same height.
|
|
7
|
+
|
|
8
|
+
A link in the title is the whole item: its hit area stretches over the item, so the icon and the
|
|
9
|
+
padding follow it too, and the item takes the link's focus ring. The link stays a real link, so
|
|
10
|
+
a router, a modified click, and "open in new tab" all work. Trailing controls sit above it and
|
|
11
|
+
stay their own. */
|
|
12
|
+
:scope {
|
|
13
|
+
position: relative;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
gap: var(--ui-list-item-gap, var(--ui-space-3));
|
|
18
|
+
min-inline-size: 0;
|
|
19
|
+
min-block-size: var(--ui-control-size, 2.5rem);
|
|
20
|
+
padding-block: var(--ui-list-item-padding-block, var(--ui-space-2));
|
|
21
|
+
padding-inline: var(--ui-list-item-padding-inline, var(--ui-space-3));
|
|
22
|
+
border-radius: var(--ui-radius-md);
|
|
23
|
+
color: var(--ui-text-primary);
|
|
24
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease), border-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:scope[data-ui-list-item-state~="variant=card"] {
|
|
28
|
+
padding-block: var(--ui-list-item-padding-block, var(--ui-space-3));
|
|
29
|
+
padding-inline: var(--ui-list-item-padding-inline, var(--ui-space-4));
|
|
30
|
+
border: 1px solid var(--ui-border-default);
|
|
31
|
+
border-radius: var(--ui-radius-lg);
|
|
32
|
+
background: var(--ui-surface-raised);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:scope:has(.title a[href]:hover) {
|
|
36
|
+
background: var(--ui-surface-hover);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
:scope[data-ui-list-item-state~="variant=card"]:has(.title a[href]:hover) {
|
|
40
|
+
border-color: var(--ui-border-strong);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
:scope[data-ui-list-item-state~="current"] {
|
|
44
|
+
background: var(--ui-surface-hover);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
:scope:has(.title a[href]:focus-visible) {
|
|
48
|
+
box-shadow: 0 0 0 2px var(--ui-focus-ring);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.leading,
|
|
52
|
+
.trailing {
|
|
53
|
+
display: inline-flex;
|
|
54
|
+
flex: none;
|
|
55
|
+
align-items: center;
|
|
56
|
+
gap: var(--ui-space-2);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.leading {
|
|
60
|
+
color: var(--ui-text-muted);
|
|
61
|
+
font-size: var(--ui-list-item-icon-size, var(--ui-font-size-lg));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Trailing controls take their own clicks, above the title link's stretched hit area. */
|
|
65
|
+
.trailing {
|
|
66
|
+
position: relative;
|
|
67
|
+
z-index: 1;
|
|
68
|
+
color: var(--ui-text-muted);
|
|
69
|
+
font-size: var(--ui-font-size-sm);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.content {
|
|
73
|
+
display: flex;
|
|
74
|
+
flex: 1;
|
|
75
|
+
flex-direction: column;
|
|
76
|
+
gap: var(--ui-space-0-5, 2px);
|
|
77
|
+
min-inline-size: 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.title,
|
|
81
|
+
.description {
|
|
82
|
+
display: block;
|
|
83
|
+
min-inline-size: 0;
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
text-overflow: ellipsis;
|
|
86
|
+
white-space: nowrap;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.title {
|
|
90
|
+
font-size: var(--ui-font-size-md);
|
|
91
|
+
font-weight: var(--ui-font-medium);
|
|
92
|
+
line-height: var(--ui-line-height-tight);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.description {
|
|
96
|
+
color: var(--ui-text-muted);
|
|
97
|
+
font-size: var(--ui-font-size-sm);
|
|
98
|
+
line-height: var(--ui-line-height-tight);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* An unused region takes no space. */
|
|
102
|
+
.leading:empty,
|
|
103
|
+
.description:empty,
|
|
104
|
+
.trailing:empty {
|
|
105
|
+
display: none;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
109
|
+
:scope[hidden] {
|
|
110
|
+
display: none;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
@scope ([data-component~="ui-list-item"]) to ([data-component]) {
|
|
114
|
+
/* One entry in a list: something to recognise (leading, usually an icon), its name (the default
|
|
115
|
+
slot), one line about it (description), and what it offers (trailing, such as a button or a
|
|
116
|
+
badge). The title and description are one line each and end in an ellipsis, so every item in a
|
|
117
|
+
list has the same height.
|
|
118
|
+
|
|
119
|
+
A link in the title is the whole item: its hit area stretches over the item, so the icon and the
|
|
120
|
+
padding follow it too, and the item takes the link's focus ring. The link stays a real link, so
|
|
121
|
+
a router, a modified click, and "open in new tab" all work. Trailing controls sit above it and
|
|
122
|
+
stay their own. */
|
|
123
|
+
|
|
124
|
+
/* Trailing controls take their own clicks, above the title link's stretched hit area. */
|
|
125
|
+
|
|
126
|
+
.title > :where([data-slotted], [data-slotted] *):is(a) {
|
|
127
|
+
color: inherit;
|
|
128
|
+
text-decoration: none;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.title > :where([data-slotted], [data-slotted] *):is(a:focus-visible) {
|
|
132
|
+
outline: none;
|
|
133
|
+
box-shadow: none;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.title > :where([data-slotted], [data-slotted] *):is(a[href])::after {
|
|
137
|
+
position: absolute;
|
|
138
|
+
inset: 0;
|
|
139
|
+
border-radius: inherit;
|
|
140
|
+
content: "";
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* An unused region takes no space. */
|
|
144
|
+
|
|
145
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
146
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* Generated by HTML Next 1.0.0-alpha.5. Do not edit. */
|
|
2
|
+
@scope ([data-component~="ui-list"]) to ([data-component], [data-slotted]) {
|
|
3
|
+
/* A list of items (ui-list-item). It owns the spacing between them, so a view never sets it. The
|
|
4
|
+
explicit list role keeps the list announced as one: some browsers drop it from a list with no
|
|
5
|
+
markers. */
|
|
6
|
+
:scope {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: var(--ui-list-gap, var(--ui-space-1));
|
|
10
|
+
min-inline-size: 0;
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
list-style: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
:scope[data-ui-list-state~="layout=grid"] {
|
|
17
|
+
display: grid;
|
|
18
|
+
grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--ui-list-min-item-width, 14rem)), 1fr));
|
|
19
|
+
gap: var(--ui-list-gap, var(--ui-space-3));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
23
|
+
:scope[hidden] {
|
|
24
|
+
display: none;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
@scope ([data-component~="ui-list"]) to ([data-component]) {
|
|
28
|
+
/* A list of items (ui-list-item). It owns the spacing between them, so a view never sets it. The
|
|
29
|
+
explicit list role keeps the list announced as one: some browsers drop it from a list with no
|
|
30
|
+
markers. */
|
|
31
|
+
|
|
32
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
33
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Generated by HTML Next 1.0.0-alpha.5 for Vanilla DOM. Do not edit.
|
|
2
|
+
export interface UiListEventMap {
|
|
3
|
+
}
|
|
4
|
+
export interface UiListElement extends HTMLUListElement {
|
|
5
|
+
addEventListener<K extends keyof UiListEventMap>(type: K, listener: (this: UiListElement, event: UiListEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
6
|
+
removeEventListener<K extends keyof UiListEventMap>(type: K, listener: (this: UiListElement, event: UiListEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
|
|
7
|
+
}
|
|
8
|
+
export interface UiListProps {
|
|
9
|
+
layout?: "rows" | "grid" | null;
|
|
10
|
+
attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
|
|
11
|
+
children?: readonly (string | Node)[];
|
|
12
|
+
slots?: Readonly<Record<string, readonly (string | Node)[]>>;
|
|
13
|
+
}
|
|
14
|
+
export declare function createUiList(props?: UiListProps): UiListElement;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Generated by HTML Next 1.0.0-alpha.5 for Vanilla DOM. Do not edit.
|
|
2
|
+
import { manageGeneratedProps } from "@nextwebwg/html-next/generated-runtime";
|
|
3
|
+
import "../styles/ui-list.css";
|
|
4
|
+
|
|
5
|
+
export function createUiList(options = {}) {
|
|
6
|
+
const { attributes = {}, children = [], slots = {}, as, ...componentProps } = options;
|
|
7
|
+
const projected = [];
|
|
8
|
+
const prop0 = componentProps["layout"] === undefined ? "rows" : componentProps["layout"];
|
|
9
|
+
const element = document.createElement("ul");
|
|
10
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
11
|
+
if (value === null || value === undefined || value === false) continue;
|
|
12
|
+
element.setAttribute(name, value === true ? "" : String(value));
|
|
13
|
+
}
|
|
14
|
+
if (!element.hasAttribute("role")) element.setAttribute("role", "list");
|
|
15
|
+
element.setAttribute("data-component", "ui-list");
|
|
16
|
+
if (children.length > 0) {
|
|
17
|
+
for (const child of children) {
|
|
18
|
+
const node = typeof child === "string" ? document.createTextNode(child) : child;
|
|
19
|
+
projected.push([node, ""]);
|
|
20
|
+
element.append(node);
|
|
21
|
+
}
|
|
22
|
+
} else {
|
|
23
|
+
}
|
|
24
|
+
manageGeneratedProps(element, [
|
|
25
|
+
{ name: "layout", attribute: "data-layout", value: componentProps["layout"], default: "rows", type: ["rows","grid"], required: false },
|
|
26
|
+
]);
|
|
27
|
+
return element;
|
|
28
|
+
}
|
|
29
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Generated by HTML Next 1.0.0-alpha.5 for Vanilla DOM. Do not edit.
|
|
2
|
+
export interface UiListItemEventMap {
|
|
3
|
+
}
|
|
4
|
+
export interface UiListItemElement extends HTMLLIElement {
|
|
5
|
+
addEventListener<K extends keyof UiListItemEventMap>(type: K, listener: (this: UiListItemElement, event: UiListItemEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
6
|
+
removeEventListener<K extends keyof UiListItemEventMap>(type: K, listener: (this: UiListItemElement, event: UiListItemEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
|
|
7
|
+
}
|
|
8
|
+
export interface UiListItemProps {
|
|
9
|
+
current?: boolean | null;
|
|
10
|
+
variant?: "row" | "card" | null;
|
|
11
|
+
attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
|
|
12
|
+
children?: readonly (string | Node)[];
|
|
13
|
+
slots?: Readonly<Record<string, readonly (string | Node)[]>>;
|
|
14
|
+
}
|
|
15
|
+
export declare function createUiListItem(props?: UiListItemProps): UiListItemElement;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Generated by HTML Next 1.0.0-alpha.5 for Vanilla DOM. Do not edit.
|
|
2
|
+
import { manageGeneratedProps } from "@nextwebwg/html-next/generated-runtime";
|
|
3
|
+
import "../styles/ui-list-item.css";
|
|
4
|
+
|
|
5
|
+
export function createUiListItem(options = {}) {
|
|
6
|
+
const { attributes = {}, children = [], slots = {}, as, ...componentProps } = options;
|
|
7
|
+
const projected = [];
|
|
8
|
+
const prop0 = componentProps["current"] === undefined ? false : componentProps["current"];
|
|
9
|
+
const prop1 = componentProps["variant"] === undefined ? "row" : componentProps["variant"];
|
|
10
|
+
const element = document.createElement("li");
|
|
11
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
12
|
+
if (value === null || value === undefined || value === false) continue;
|
|
13
|
+
element.setAttribute(name, value === true ? "" : String(value));
|
|
14
|
+
}
|
|
15
|
+
const value0 = prop0;
|
|
16
|
+
if (typeof value0 === "boolean") element.setAttribute("aria-current", String(value0));
|
|
17
|
+
else element.removeAttribute("aria-current");
|
|
18
|
+
element.setAttribute("data-component", "ui-list-item");
|
|
19
|
+
const element0 = document.createElement("span");
|
|
20
|
+
element0.setAttribute("class", "leading");
|
|
21
|
+
if (slots["leading"] ?? [].length > 0) {
|
|
22
|
+
for (const child of slots["leading"] ?? []) {
|
|
23
|
+
const node = typeof child === "string" ? document.createTextNode(child) : child;
|
|
24
|
+
projected.push([node, "leading"]);
|
|
25
|
+
element0.append(node);
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
}
|
|
29
|
+
element.append(element0);
|
|
30
|
+
const element1 = document.createElement("span");
|
|
31
|
+
element1.setAttribute("class", "content");
|
|
32
|
+
const element2 = document.createElement("span");
|
|
33
|
+
element2.setAttribute("class", "title");
|
|
34
|
+
if (children.length > 0) {
|
|
35
|
+
for (const child of children) {
|
|
36
|
+
const node = typeof child === "string" ? document.createTextNode(child) : child;
|
|
37
|
+
projected.push([node, ""]);
|
|
38
|
+
element2.append(node);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
}
|
|
42
|
+
element1.append(element2);
|
|
43
|
+
const element3 = document.createElement("span");
|
|
44
|
+
element3.setAttribute("class", "description");
|
|
45
|
+
if (slots["description"] ?? [].length > 0) {
|
|
46
|
+
for (const child of slots["description"] ?? []) {
|
|
47
|
+
const node = typeof child === "string" ? document.createTextNode(child) : child;
|
|
48
|
+
projected.push([node, "description"]);
|
|
49
|
+
element3.append(node);
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
}
|
|
53
|
+
element1.append(element3);
|
|
54
|
+
element.append(element1);
|
|
55
|
+
const element4 = document.createElement("span");
|
|
56
|
+
element4.setAttribute("class", "trailing");
|
|
57
|
+
if (slots["trailing"] ?? [].length > 0) {
|
|
58
|
+
for (const child of slots["trailing"] ?? []) {
|
|
59
|
+
const node = typeof child === "string" ? document.createTextNode(child) : child;
|
|
60
|
+
projected.push([node, "trailing"]);
|
|
61
|
+
element4.append(node);
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
}
|
|
65
|
+
element.append(element4);
|
|
66
|
+
manageGeneratedProps(element, [
|
|
67
|
+
{ name: "current", attribute: "data-current", value: componentProps["current"], default: false, type: "boolean", required: false },
|
|
68
|
+
{ name: "variant", attribute: "data-variant", value: componentProps["variant"], default: "row", type: ["row","card"], required: false },
|
|
69
|
+
], (name, value) => {
|
|
70
|
+
if (name === "current") {
|
|
71
|
+
if (value === null || value === undefined) element.removeAttribute("aria-current");
|
|
72
|
+
else element.setAttribute("aria-current", String(value));
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return element;
|
|
76
|
+
}
|
|
77
|
+
|
package/vanilla/index.js
CHANGED
|
@@ -25,6 +25,8 @@ export * from "./UiGrid.js";
|
|
|
25
25
|
export * from "./UiIcon.js";
|
|
26
26
|
export * from "./UiIconButton.js";
|
|
27
27
|
export * from "./UiInput.js";
|
|
28
|
+
export * from "./UiList.js";
|
|
29
|
+
export * from "./UiListItem.js";
|
|
28
30
|
export * from "./UiMenu.js";
|
|
29
31
|
export * from "./UiMenuItem.js";
|
|
30
32
|
export * from "./UiPopover.js";
|
package/vue/UiList.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
layout?: 'rows' | 'grid';
|
|
3
|
+
};
|
|
4
|
+
declare var __VLS_1: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_1) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
9
|
+
layout: "rows" | "grid";
|
|
10
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
package/vue/UiList.js
ADDED
package/vue/UiList.vue
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<!-- Generated by HTML Next 1.0.0-alpha.5 for Vue 3.5. Do not edit. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
|
|
5
|
+
defineOptions({ inheritAttrs: false })
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(
|
|
8
|
+
defineProps<{
|
|
9
|
+
layout?: 'rows' | 'grid'
|
|
10
|
+
}>(),
|
|
11
|
+
{
|
|
12
|
+
layout: 'rows',
|
|
13
|
+
},
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
/** The values the styles' :host-state() rules test. */
|
|
17
|
+
const hostState = computed(() =>
|
|
18
|
+
[
|
|
19
|
+
props.layout && `layout layout=${props.layout}`,
|
|
20
|
+
].filter(Boolean).join(' ')
|
|
21
|
+
)
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<ul
|
|
26
|
+
data-component="ui-list"
|
|
27
|
+
role="list"
|
|
28
|
+
v-bind="$attrs"
|
|
29
|
+
:data-ui-list-state="hostState || undefined"
|
|
30
|
+
>
|
|
31
|
+
<slot />
|
|
32
|
+
</ul>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<style scoped>
|
|
36
|
+
/* A list of items (ui-list-item). It owns the spacing between them, so a view never sets it. The
|
|
37
|
+
explicit list role keeps the list announced as one: some browsers drop it from a list with no
|
|
38
|
+
markers. */
|
|
39
|
+
[data-component~="ui-list"] {
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
gap: var(--ui-list-gap, var(--ui-space-1));
|
|
43
|
+
min-inline-size: 0;
|
|
44
|
+
margin: 0;
|
|
45
|
+
padding: 0;
|
|
46
|
+
list-style: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
[data-component~="ui-list"][data-ui-list-state~="layout=grid"] {
|
|
50
|
+
display: grid;
|
|
51
|
+
grid-template-columns:
|
|
52
|
+
repeat(auto-fill, minmax(min(100%, var(--ui-list-min-item-width, 14rem)), 1fr));
|
|
53
|
+
gap: var(--ui-list-gap, var(--ui-space-3));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
57
|
+
[data-component~="ui-list"][hidden] {
|
|
58
|
+
display: none;
|
|
59
|
+
}
|
|
60
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
current?: boolean;
|
|
3
|
+
variant?: 'row' | 'card';
|
|
4
|
+
};
|
|
5
|
+
declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {}, __VLS_7: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
leading?: (props: typeof __VLS_1) => any;
|
|
8
|
+
} & {
|
|
9
|
+
default?: (props: typeof __VLS_3) => any;
|
|
10
|
+
} & {
|
|
11
|
+
description?: (props: typeof __VLS_5) => any;
|
|
12
|
+
} & {
|
|
13
|
+
trailing?: (props: typeof __VLS_7) => any;
|
|
14
|
+
};
|
|
15
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
16
|
+
variant: "row" | "card";
|
|
17
|
+
current: boolean;
|
|
18
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
19
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
|
22
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
23
|
+
new (): {
|
|
24
|
+
$slots: S;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<!-- Generated by HTML Next 1.0.0-alpha.5 for Vue 3.5. Do not edit. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
|
|
5
|
+
defineOptions({ inheritAttrs: false })
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(
|
|
8
|
+
defineProps<{
|
|
9
|
+
current?: boolean
|
|
10
|
+
variant?: 'row' | 'card'
|
|
11
|
+
}>(),
|
|
12
|
+
{
|
|
13
|
+
current: false,
|
|
14
|
+
variant: 'row',
|
|
15
|
+
},
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
/** The values the styles' :host-state() rules test. */
|
|
19
|
+
const hostState = computed(() =>
|
|
20
|
+
[
|
|
21
|
+
props.variant && `variant variant=${props.variant}`,
|
|
22
|
+
props.current && 'current',
|
|
23
|
+
].filter(Boolean).join(' ')
|
|
24
|
+
)
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<li
|
|
29
|
+
data-component="ui-list-item"
|
|
30
|
+
v-bind="$attrs"
|
|
31
|
+
:aria-current="current"
|
|
32
|
+
:data-ui-list-item-state="hostState || undefined"
|
|
33
|
+
>
|
|
34
|
+
<span class="leading"><slot name="leading" /></span>
|
|
35
|
+
<span class="content"><span class="title"><slot /></span>
|
|
36
|
+
<span class="description"><slot name="description" /></span></span>
|
|
37
|
+
<span class="trailing"><slot name="trailing" /></span>
|
|
38
|
+
</li>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<style scoped>
|
|
42
|
+
/* One entry in a list: something to recognise (leading, usually an icon), its name (the default
|
|
43
|
+
slot), one line about it (description), and what it offers (trailing, such as a button or a
|
|
44
|
+
badge). The title and description are one line each and end in an ellipsis, so every item in a
|
|
45
|
+
list has the same height.
|
|
46
|
+
|
|
47
|
+
A link in the title is the whole item: its hit area stretches over the item, so the icon and the
|
|
48
|
+
padding follow it too, and the item takes the link's focus ring. The link stays a real link, so
|
|
49
|
+
a router, a modified click, and "open in new tab" all work. Trailing controls sit above it and
|
|
50
|
+
stay their own. */
|
|
51
|
+
[data-component~="ui-list-item"] {
|
|
52
|
+
position: relative;
|
|
53
|
+
box-sizing: border-box;
|
|
54
|
+
display: flex;
|
|
55
|
+
align-items: center;
|
|
56
|
+
gap: var(--ui-list-item-gap, var(--ui-space-3));
|
|
57
|
+
min-inline-size: 0;
|
|
58
|
+
min-block-size: var(--ui-control-size, 2.5rem);
|
|
59
|
+
padding-block: var(--ui-list-item-padding-block, var(--ui-space-2));
|
|
60
|
+
padding-inline: var(--ui-list-item-padding-inline, var(--ui-space-3));
|
|
61
|
+
border-radius: var(--ui-radius-md);
|
|
62
|
+
color: var(--ui-text-primary);
|
|
63
|
+
transition:
|
|
64
|
+
background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
65
|
+
border-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
[data-component~="ui-list-item"][data-ui-list-item-state~="variant=card"] {
|
|
69
|
+
padding-block: var(--ui-list-item-padding-block, var(--ui-space-3));
|
|
70
|
+
padding-inline: var(--ui-list-item-padding-inline, var(--ui-space-4));
|
|
71
|
+
border: 1px solid var(--ui-border-default);
|
|
72
|
+
border-radius: var(--ui-radius-lg);
|
|
73
|
+
background: var(--ui-surface-raised);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
[data-component~="ui-list-item"]:has(.title a[href]:hover) {
|
|
77
|
+
background: var(--ui-surface-hover);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
[data-component~="ui-list-item"][data-ui-list-item-state~="variant=card"]:has(.title
|
|
81
|
+
a[href]:hover) {
|
|
82
|
+
border-color: var(--ui-border-strong);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
[data-component~="ui-list-item"][data-ui-list-item-state~="current"] {
|
|
86
|
+
background: var(--ui-surface-hover);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
[data-component~="ui-list-item"]:has(.title a[href]:focus-visible) {
|
|
90
|
+
box-shadow: 0 0 0 2px var(--ui-focus-ring);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.leading,
|
|
94
|
+
.trailing {
|
|
95
|
+
display: inline-flex;
|
|
96
|
+
flex: none;
|
|
97
|
+
align-items: center;
|
|
98
|
+
gap: var(--ui-space-2);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.leading {
|
|
102
|
+
color: var(--ui-text-muted);
|
|
103
|
+
font-size: var(--ui-list-item-icon-size, var(--ui-font-size-lg));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Trailing controls take their own clicks, above the title link's stretched hit area. */
|
|
107
|
+
.trailing {
|
|
108
|
+
position: relative;
|
|
109
|
+
z-index: 1;
|
|
110
|
+
color: var(--ui-text-muted);
|
|
111
|
+
font-size: var(--ui-font-size-sm);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.content {
|
|
115
|
+
display: flex;
|
|
116
|
+
flex: 1;
|
|
117
|
+
flex-direction: column;
|
|
118
|
+
gap: var(--ui-space-0-5, 2px);
|
|
119
|
+
min-inline-size: 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.title,
|
|
123
|
+
.description {
|
|
124
|
+
display: block;
|
|
125
|
+
min-inline-size: 0;
|
|
126
|
+
overflow: hidden;
|
|
127
|
+
text-overflow: ellipsis;
|
|
128
|
+
white-space: nowrap;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.title {
|
|
132
|
+
font-size: var(--ui-font-size-md);
|
|
133
|
+
font-weight: var(--ui-font-medium);
|
|
134
|
+
line-height: var(--ui-line-height-tight);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.description {
|
|
138
|
+
color: var(--ui-text-muted);
|
|
139
|
+
font-size: var(--ui-font-size-sm);
|
|
140
|
+
line-height: var(--ui-line-height-tight);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.title > :slotted(a) {
|
|
144
|
+
color: inherit;
|
|
145
|
+
text-decoration: none;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.title > :slotted(a:focus-visible) {
|
|
149
|
+
outline: none;
|
|
150
|
+
box-shadow: none;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.title > :slotted(a[href])::after {
|
|
154
|
+
position: absolute;
|
|
155
|
+
inset: 0;
|
|
156
|
+
border-radius: inherit;
|
|
157
|
+
content: "";
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* An unused region takes no space. */
|
|
161
|
+
.leading:empty,
|
|
162
|
+
.description:empty,
|
|
163
|
+
.trailing:empty {
|
|
164
|
+
display: none;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
168
|
+
[data-component~="ui-list-item"][hidden] {
|
|
169
|
+
display: none;
|
|
170
|
+
}
|
|
171
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
|
|
2
|
+
import { computed, createElementBlock, defineComponent, mergeProps, openBlock, renderSlot } from "vue";
|
|
3
|
+
//#region .build/vue/UiList.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var _hoisted_1 = ["data-ui-list-state"];
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region .build/vue/UiList.vue
|
|
7
|
+
var UiList_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
|
|
8
|
+
inheritAttrs: false,
|
|
9
|
+
__name: "UiList",
|
|
10
|
+
props: { layout: { default: "rows" } },
|
|
11
|
+
setup(__props) {
|
|
12
|
+
const props = __props;
|
|
13
|
+
/** The values the styles' :host-state() rules test. */
|
|
14
|
+
const hostState = computed(() => [props.layout && `layout layout=${props.layout}`].filter(Boolean).join(" "));
|
|
15
|
+
return (_ctx, _cache) => {
|
|
16
|
+
return openBlock(), createElementBlock("ul", mergeProps({
|
|
17
|
+
"data-component": "ui-list",
|
|
18
|
+
role: "list"
|
|
19
|
+
}, _ctx.$attrs, { "data-ui-list-state": hostState.value || void 0 }), [renderSlot(_ctx.$slots, "default", {}, void 0, true)], 16, _hoisted_1);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}), [["__scopeId", "data-v-935b1197"]]);
|
|
23
|
+
//#endregion
|
|
24
|
+
export { UiList_default as t };
|