lutra 0.0.13 → 0.0.15
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/data/Stat.svelte +1 -1
- package/dist/display/Avatar.svelte +1 -1
- package/dist/display/Badge.svelte +1 -1
- package/dist/display/Callout.svelte +3 -3
- package/dist/display/Code.svelte +1 -1
- package/dist/display/ContextTip.svelte +1 -1
- package/dist/display/Details.svelte +1 -1
- package/dist/display/Hero.svelte +1 -1
- package/dist/display/Icon.svelte +9 -3
- package/dist/display/IconButton.svelte +9 -9
- package/dist/display/IconButton.svelte.d.ts +0 -2
- package/dist/display/Image.svelte +41 -0
- package/dist/display/Image.svelte.d.ts +24 -0
- package/dist/display/Indicator.svelte +1 -1
- package/dist/display/Inset.svelte +18 -0
- package/dist/display/Inset.svelte.d.ts +17 -0
- package/dist/display/Popup.svelte +1 -1
- package/dist/display/Popup.svelte.d.ts +1 -3
- package/dist/display/Table.svelte +21 -0
- package/dist/display/Table.svelte.d.ts +23 -0
- package/dist/display/Tag.svelte +2 -2
- package/dist/display/Tooltip.svelte +1 -1
- package/dist/display/index.d.ts +1 -0
- package/dist/display/index.js +1 -0
- package/dist/form/Button.svelte +1 -1
- package/dist/form/FieldActions.svelte +26 -6
- package/dist/form/FieldActions.svelte.d.ts +1 -0
- package/dist/form/FieldContainer.svelte +4 -3
- package/dist/form/FieldContent.svelte +54 -16
- package/dist/form/FieldError.svelte +1 -1
- package/dist/form/FieldSection.svelte +20 -47
- package/dist/form/Fieldset.svelte +10 -5
- package/dist/form/Fieldset.svelte.d.ts +2 -0
- package/dist/form/Form.svelte +1 -1
- package/dist/form/Input.svelte +19 -40
- package/dist/form/Input.svelte.d.ts +2 -0
- package/dist/form/InputLength.svelte +1 -1
- package/dist/form/Label.svelte +2 -1
- package/dist/form/Select.svelte +1 -1
- package/dist/grid/Column.svelte +1 -1
- package/dist/grid/Grid.svelte +1 -1
- package/dist/grid/Row.svelte +1 -1
- package/dist/icons/Alert.svelte +2 -2
- package/dist/icons/Copy.svelte +2 -2
- package/dist/icons/Done.svelte +2 -2
- package/dist/icons/Error.svelte +2 -2
- package/dist/icons/Help.svelte +2 -2
- package/dist/icons/Hide.svelte +2 -2
- package/dist/icons/Info.svelte +2 -2
- package/dist/icons/Link.svelte +2 -2
- package/dist/icons/MenuBurger.svelte +3 -0
- package/dist/icons/MenuBurger.svelte.d.ts +23 -0
- package/dist/icons/MenuDots.svelte +3 -0
- package/dist/icons/MenuDots.svelte.d.ts +23 -0
- package/dist/icons/Show.svelte +2 -2
- package/dist/icons/Success.svelte +2 -2
- package/dist/icons/Warning.svelte +2 -2
- package/dist/layout/Layout.svelte +1 -1
- package/dist/layout/LayoutFooter.svelte +1 -1
- package/dist/layout/LayoutGrid.svelte +1 -1
- package/dist/layout/LayoutHeader.svelte +1 -1
- package/dist/layout/PageContent.svelte +1 -1
- package/dist/layout/Theme.svelte +7 -7
- package/dist/layout/UIContent.svelte +1 -1
- package/dist/nav/Breadcrumb.svelte +1 -1
- package/dist/nav/Menu.svelte +177 -161
- package/dist/nav/Menu.svelte.d.ts +11 -3
- package/dist/nav/MenuItem.svelte +122 -0
- package/dist/nav/MenuItem.svelte.d.ts +17 -0
- package/dist/nav/MenuTypes.d.ts +24 -3
- package/dist/nav/NavMenu.svelte +183 -0
- package/dist/nav/NavMenu.svelte.d.ts +18 -0
- package/dist/nav/TabbedContent.svelte +1 -1
- package/dist/nav/Tabs.svelte +8 -8
- package/dist/nav/index.d.ts +2 -0
- package/dist/nav/index.js +1 -0
- package/dist/style.css +36 -24
- package/dist/typo/Clamp.svelte +1 -1
- package/dist/typo/H.svelte +3 -2
- package/dist/typo/H.svelte.d.ts +2 -0
- package/dist/typo/H1.svelte +3 -3
- package/dist/typo/H1.svelte.d.ts +2 -0
- package/dist/typo/H2.svelte +3 -2
- package/dist/typo/H2.svelte.d.ts +2 -0
- package/dist/typo/H3.svelte +3 -2
- package/dist/typo/H3.svelte.d.ts +2 -0
- package/dist/typo/H4.svelte +3 -2
- package/dist/typo/H4.svelte.d.ts +2 -0
- package/dist/typo/H5.svelte +3 -2
- package/dist/typo/H5.svelte.d.ts +2 -0
- package/dist/typo/H6.svelte +3 -2
- package/dist/typo/H6.svelte.d.ts +2 -0
- package/dist/typo/P.svelte +3 -1
- package/dist/typo/P.svelte.d.ts +2 -0
- package/dist/utils/StringOrComponentOrSnippet.svelte +13 -0
- package/dist/utils/StringOrComponentOrSnippet.svelte.d.ts +17 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/keyboard.svelte.d.ts +3 -0
- package/dist/utils/keyboard.svelte.js +142 -0
- package/dist/utils/transitions.js +14 -7
- package/package.json +9 -13
- package/dist/datatable/DataTable.svelte +0 -31
- package/dist/datatable/DataTable.svelte.d.ts +0 -20
- package/dist/datatable/DataTableColumn.svelte +0 -20
- package/dist/datatable/DataTableColumn.svelte.d.ts +0 -18
- package/dist/datatable/DataTableRow.svelte +0 -59
- package/dist/datatable/DataTableRow.svelte.d.ts +0 -21
- package/dist/datatable/index.d.ts +0 -3
- package/dist/datatable/index.js +0 -3
- package/dist/form/server.d.ts +0 -21
- package/dist/form/server.js +0 -48
package/dist/nav/Menu.svelte
CHANGED
@@ -1,180 +1,196 @@
|
|
1
|
-
<script>import
|
1
|
+
<script lang="ts">import MenuItem from "./MenuItem.svelte";
|
2
|
+
import { isComponent } from "../utils/isSnippet.js";
|
3
|
+
import { createId } from "../utils/id.js";
|
4
|
+
import { slidefade } from "../utils/transitions.js";
|
5
|
+
import UiContent from "../layout/UIContent.svelte";
|
6
|
+
import { arrowNavigation, getNextFocusableElement, matchOnType } from "../utils/keyboard.svelte.js";
|
7
|
+
import StringOrComponentOrSnippet from "../utils/StringOrComponentOrSnippet.svelte";
|
2
8
|
let {
|
3
|
-
|
9
|
+
open = $bindable(false),
|
10
|
+
items,
|
11
|
+
trigger
|
4
12
|
} = $props();
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
let _open = $state(open);
|
14
|
+
let triggerEl = $state(null);
|
15
|
+
let contentEl = $state(null);
|
16
|
+
let menuEl = $state(null);
|
17
|
+
let menuHeight = $state(0);
|
18
|
+
let menuWidth = $state(0);
|
19
|
+
const id = createId();
|
20
|
+
const fudge = 16;
|
21
|
+
$effect(() => {
|
22
|
+
if (_open) {
|
23
|
+
window.addEventListener("click", clickoutside);
|
24
|
+
window.addEventListener("keydown", onkeydown);
|
25
|
+
} else {
|
26
|
+
window.removeEventListener("click", clickoutside);
|
27
|
+
window.removeEventListener("keydown", onkeydown);
|
16
28
|
}
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
};
|
29
|
+
});
|
30
|
+
function toggle() {
|
31
|
+
_open = !_open;
|
21
32
|
}
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
let origin = $derived.by(() => {
|
34
|
+
if (!triggerEl || !contentEl)
|
35
|
+
return "top-left";
|
36
|
+
const triggerPos = triggerEl.getBoundingClientRect();
|
37
|
+
const elPos = contentEl.getBoundingClientRect();
|
38
|
+
const isOffRight = triggerPos.left + elPos.width > window.innerWidth - fudge;
|
39
|
+
const isOffBottom = triggerPos.bottom + elPos.height > window.innerHeight - fudge;
|
40
|
+
let text = "top left";
|
41
|
+
if (isOffRight)
|
42
|
+
text = text.replace("left", "right");
|
43
|
+
if (isOffBottom)
|
44
|
+
text = text.replace("top", "bottom");
|
45
|
+
return text;
|
46
|
+
});
|
47
|
+
let posLeft = $derived.by(() => {
|
48
|
+
if (!triggerEl || !contentEl)
|
49
|
+
return 0;
|
50
|
+
const triggerPos = triggerEl.getBoundingClientRect();
|
51
|
+
const isOffRight = triggerPos.left + menuWidth > window.innerWidth - fudge;
|
52
|
+
if (isOffRight) {
|
53
|
+
return triggerPos.left + triggerPos.width - menuWidth;
|
54
|
+
}
|
55
|
+
return triggerPos.left;
|
56
|
+
});
|
57
|
+
let posTop = $derived.by(() => {
|
58
|
+
if (!triggerEl || !contentEl)
|
59
|
+
return 0;
|
60
|
+
const triggerPos = triggerEl.getBoundingClientRect();
|
61
|
+
const scrollY = window.scrollY;
|
62
|
+
const isOffBottom = triggerPos.bottom + menuHeight > window.innerHeight - fudge;
|
63
|
+
if (isOffBottom) {
|
64
|
+
return triggerPos.top - menuHeight - triggerPos.height + scrollY;
|
65
|
+
}
|
66
|
+
return triggerPos.top + scrollY;
|
67
|
+
});
|
68
|
+
function onclick(e) {
|
69
|
+
e.preventDefault();
|
70
|
+
_open = !_open;
|
71
|
+
}
|
72
|
+
function clickoutside(e) {
|
73
|
+
if (!_open)
|
74
|
+
return;
|
75
|
+
if (contentEl && !contentEl.contains(e.target) && !triggerEl?.contains(e.target)) {
|
76
|
+
_open = false;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
function onkeydown(e) {
|
80
|
+
if (!_open)
|
81
|
+
return;
|
82
|
+
const active = document.activeElement;
|
83
|
+
switch (e.key) {
|
84
|
+
case "Escape":
|
85
|
+
e.preventDefault();
|
86
|
+
_open = false;
|
87
|
+
break;
|
88
|
+
case "Tab":
|
89
|
+
e.preventDefault();
|
90
|
+
e.stopPropagation();
|
91
|
+
_open = false;
|
92
|
+
setTimeout(() => {
|
93
|
+
const nextEl = getNextFocusableElement(menuEl, triggerEl, e.shiftKey ? "previous" : "next");
|
94
|
+
console.log("nextEl", nextEl);
|
95
|
+
if (nextEl) {
|
96
|
+
nextEl.focus();
|
97
|
+
if (nextEl.tagName === "BUTTON" || nextEl.tagName === "A" && nextEl.parentElement?.classList.contains("Trigger")) {
|
98
|
+
nextEl.click();
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}, 0);
|
102
|
+
break;
|
103
|
+
case "ArrowDown":
|
104
|
+
e.preventDefault();
|
105
|
+
arrowNavigation(contentEl, "down");
|
106
|
+
matchOnType(contentEl, e);
|
107
|
+
break;
|
108
|
+
case "ArrowUp":
|
109
|
+
e.preventDefault();
|
110
|
+
arrowNavigation(contentEl, "up");
|
111
|
+
matchOnType(contentEl, e);
|
112
|
+
break;
|
113
|
+
case "Enter":
|
114
|
+
case "Space":
|
115
|
+
e.preventDefault();
|
116
|
+
active.click();
|
117
|
+
break;
|
118
|
+
default:
|
119
|
+
matchOnType(contentEl, e);
|
120
|
+
}
|
37
121
|
}
|
38
|
-
const parsedItems = parseLinks(items);
|
39
122
|
</script>
|
40
123
|
|
41
|
-
<
|
42
|
-
<
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
{:
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
{
|
60
|
-
{
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
{/
|
72
|
-
</
|
73
|
-
</
|
124
|
+
<UiContent>
|
125
|
+
<div class="Menu" bind:this={menuEl}>
|
126
|
+
<div
|
127
|
+
class="Trigger"
|
128
|
+
bind:this={triggerEl}
|
129
|
+
>
|
130
|
+
{#if typeof trigger === "string" || isComponent(trigger)}
|
131
|
+
<button type="button" class="button" {onclick} aria-haspopup="true" aria-controls={id} aria-expanded="{_open}">
|
132
|
+
<StringOrComponentOrSnippet content={trigger} />
|
133
|
+
</button>
|
134
|
+
{:else}
|
135
|
+
{@render trigger({ toggle: toggle, isOpen: _open })}
|
136
|
+
{/if}
|
137
|
+
</div>
|
138
|
+
{#if _open}
|
139
|
+
<div {id}
|
140
|
+
class="MenuContent"
|
141
|
+
role="menu"
|
142
|
+
bind:clientWidth={menuWidth}
|
143
|
+
bind:clientHeight={menuHeight}
|
144
|
+
bind:this={contentEl}
|
145
|
+
style="--left: {posLeft}px; --top: {posTop}px;"
|
146
|
+
transition:slidefade={{ y: 5, origin: origin, duration: 100 }}
|
147
|
+
>
|
148
|
+
<ul>
|
149
|
+
{#each items as item}
|
150
|
+
<MenuItem item={item} />
|
151
|
+
{/each}
|
152
|
+
</ul>
|
153
|
+
</div>
|
154
|
+
{/if}
|
155
|
+
</div>
|
156
|
+
</UiContent>
|
74
157
|
|
75
158
|
<style>
|
76
|
-
|
77
|
-
}
|
78
|
-
ul {
|
79
|
-
display: flex;
|
80
|
-
list-style: none;
|
81
|
-
padding: 0;
|
82
|
-
margin: 0;
|
83
|
-
}
|
84
|
-
a, span {
|
85
|
-
display: flex;
|
86
|
-
align-items: center;
|
87
|
-
padding: 0.5rem 0.75rem;
|
88
|
-
text-decoration: none;
|
89
|
-
font-weight: 500;
|
90
|
-
color: var(--menu-link);
|
91
|
-
}
|
92
|
-
a:hover, span:hover {
|
93
|
-
background: var(--menu-bg-hover);
|
94
|
-
color: var(--menu-link-hover);
|
95
|
-
}
|
96
|
-
/** loop */
|
97
|
-
ul > li > ul {
|
98
|
-
display: none;
|
99
|
-
position: absolute;
|
100
|
-
flex-direction: column;
|
101
|
-
top: 100%;
|
102
|
-
left: 0;
|
103
|
-
background: var(--menu-bg);
|
104
|
-
border: var(--menu-border);
|
105
|
-
}
|
106
|
-
ul > li:hover > ul,
|
107
|
-
ul > li:focus-within > ul {
|
108
|
-
display: flex;
|
109
|
-
}
|
110
|
-
ul > li:hover,
|
111
|
-
ul > li:focus-within {
|
112
|
-
background: var(--menu-bg-hover);
|
113
|
-
}
|
114
|
-
ul > li:hover > a,
|
115
|
-
ul > li:focus-within > a,
|
116
|
-
ul > li:hover > span,
|
117
|
-
ul > li:focus-within > span {
|
118
|
-
color: var(--menu-link-hover);
|
119
|
-
}
|
120
|
-
|
121
|
-
ul > li {
|
122
|
-
border-block-end: var(--menu-border);
|
159
|
+
.Menu {
|
123
160
|
position: relative;
|
124
|
-
white-space: nowrap;
|
125
161
|
}
|
126
|
-
|
127
|
-
|
128
|
-
}
|
129
|
-
ul > li > ul {
|
130
|
-
left: 100%;
|
131
|
-
top: -1px;
|
132
|
-
}
|
133
|
-
ul > li:has(ul) > a {
|
134
|
-
padding-inline-end: 2rem;
|
135
|
-
}
|
136
|
-
ul > li:has(ul) > a::after {
|
137
|
-
content: "▶";
|
138
|
-
padding-inline-start: 0.5rem;
|
139
|
-
font-size: 9px;
|
140
|
-
position: absolute;
|
141
|
-
right: 0.75rem;
|
142
|
-
color: var(--menu-link);
|
143
|
-
}
|
144
|
-
/** top level */
|
145
|
-
nav > ul {
|
146
|
-
flex-direction: row;
|
147
|
-
gap: 1px;
|
162
|
+
|
163
|
+
.Trigger {
|
148
164
|
position: relative;
|
165
|
+
display: inline-flex;
|
149
166
|
}
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
167
|
+
|
168
|
+
.MenuContent {
|
169
|
+
position: fixed;
|
170
|
+
left: var(--left, 0);
|
171
|
+
top: var(--top, 0);
|
172
|
+
margin: 0;
|
173
|
+
z-index: 1000;
|
174
|
+
margin: 0;
|
175
|
+
border: var(--menu-border);
|
157
176
|
border-radius: var(--border-radius);
|
177
|
+
box-shadow: 0 0.5rem 1rem var(--shadow);
|
178
|
+
background-color: var(--menu-bg);
|
179
|
+
width: var(--width, 25ch);
|
180
|
+
overflow: clip;
|
158
181
|
}
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
background: var(--menu-bg);
|
163
|
-
border: var(--menu-border);
|
164
|
-
filter: drop-shadow(0 0.25rem 0.5rem var(--shadow));
|
182
|
+
|
183
|
+
.MenuContent:has(li:last-of-type[data-type="item"]) {
|
184
|
+
padding-block-end: 0.5rem;
|
165
185
|
}
|
166
|
-
|
167
|
-
|
186
|
+
|
187
|
+
nav[aria-expanded="true"] {
|
188
|
+
display: block;
|
168
189
|
}
|
169
|
-
|
170
|
-
|
190
|
+
|
191
|
+
ul {
|
192
|
+
margin: 0;
|
193
|
+
list-style: none;
|
171
194
|
padding: 0;
|
172
195
|
}
|
173
|
-
|
174
|
-
background: var(--menu-bg-active);
|
175
|
-
color: var(--menu-link-active);
|
176
|
-
}
|
177
|
-
ul > li[aria-current="page"] a:hover {
|
178
|
-
color: var(--menu-link-active-hover);
|
179
|
-
}
|
180
|
-
</style>
|
196
|
+
</style>
|
@@ -1,9 +1,17 @@
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
2
|
-
import type {
|
2
|
+
import type { ComponentType, Snippet } from "svelte";
|
3
|
+
import type { MenuItem as Item } from "./MenuTypes.js";
|
3
4
|
declare const __propDef: {
|
4
5
|
props: {
|
5
|
-
/**
|
6
|
-
|
6
|
+
/** Whether the menu is open */
|
7
|
+
open?: boolean | undefined;
|
8
|
+
/** The items to display in the menu */
|
9
|
+
items: Item[];
|
10
|
+
/** The trigger for the menu */
|
11
|
+
trigger: string | ComponentType | Snippet<[{
|
12
|
+
toggle: () => void;
|
13
|
+
isOpen: boolean;
|
14
|
+
}]>;
|
7
15
|
};
|
8
16
|
events: {
|
9
17
|
[evt: string]: CustomEvent<any>;
|
@@ -0,0 +1,122 @@
|
|
1
|
+
<script lang="ts">import StringOrComponentOrSnippet from "../utils/StringOrComponentOrSnippet.svelte";
|
2
|
+
import { isStatusColor } from "../utils/color.js";
|
3
|
+
import { isComponent, isSnippet } from "../utils/isSnippet.js";
|
4
|
+
let {
|
5
|
+
item
|
6
|
+
} = $props();
|
7
|
+
let isSet = $derived(item.type !== "divider" ? isStatusColor(item.color) : false);
|
8
|
+
</script>
|
9
|
+
|
10
|
+
<li class:divider={item.type === 'divider'} class:header={item.type === 'header'} data-type="{item.type}" style="--color: {isSet && item.type !== 'divider' ? 'var(--status-'+item.color+')' : (item.type !== 'divider' && item.color ? item.color : 'var(--menu-text)')}">
|
11
|
+
{#if item.type === 'divider'}
|
12
|
+
<hr />
|
13
|
+
{:else if item.type === 'header'}
|
14
|
+
<div class="Header">
|
15
|
+
<StringOrComponentOrSnippet content={item.content} />
|
16
|
+
</div>
|
17
|
+
{:else if item.type === 'item'}
|
18
|
+
{#if item.href}
|
19
|
+
<a href="{item.href}" class="Item">
|
20
|
+
<span class="Content">
|
21
|
+
<StringOrComponentOrSnippet content={item.content} />
|
22
|
+
</span>
|
23
|
+
{#if item.shortcut}
|
24
|
+
<span class="Shortcut">{item.shortcut}</span>
|
25
|
+
{/if}
|
26
|
+
</a>
|
27
|
+
{:else if item.onclick}
|
28
|
+
<button type="button" onclick={(e) => item.type === 'item' ? item.onclick!(e, item) : undefined} class="Item">
|
29
|
+
<span class="Content">
|
30
|
+
<StringOrComponentOrSnippet content={item.content} />
|
31
|
+
</span>
|
32
|
+
{#if item.shortcut}
|
33
|
+
<span class="Shortcut">{item.shortcut}</span>
|
34
|
+
{/if}
|
35
|
+
</button>
|
36
|
+
{:else if isSnippet(item.content)}
|
37
|
+
<div class="Item Custom">
|
38
|
+
{@render item.content()}
|
39
|
+
</div>
|
40
|
+
{:else if isComponent(item.content)}
|
41
|
+
<div class="Item Custom">
|
42
|
+
<svelte:component this={item.content} />
|
43
|
+
</div>
|
44
|
+
{/if}
|
45
|
+
{/if}
|
46
|
+
</li>
|
47
|
+
|
48
|
+
<style>
|
49
|
+
li {
|
50
|
+
margin: 0;
|
51
|
+
list-style: none;
|
52
|
+
padding: 0;
|
53
|
+
user-select: none;
|
54
|
+
}
|
55
|
+
|
56
|
+
li .Item,
|
57
|
+
li .Header {
|
58
|
+
font-size: 1em;
|
59
|
+
text-align: left;
|
60
|
+
padding-block: 0.5rem;
|
61
|
+
padding-inline: 1rem;
|
62
|
+
display: inline-flex;
|
63
|
+
align-items: center;
|
64
|
+
justify-content: space-between;
|
65
|
+
width: 100%;
|
66
|
+
color: inherit;
|
67
|
+
text-decoration: none;
|
68
|
+
color: var(--color);
|
69
|
+
--inset-block: 0.5rem;
|
70
|
+
--inset-inline: 1rem;
|
71
|
+
}
|
72
|
+
|
73
|
+
li .Header {
|
74
|
+
font-weight: 600;
|
75
|
+
}
|
76
|
+
|
77
|
+
li .Item:not(.Custom):hover,
|
78
|
+
li .Item:not(.Custom):focus-visible {
|
79
|
+
background-color: var(--menu-bg-hover);
|
80
|
+
cursor: pointer;
|
81
|
+
outline: none;
|
82
|
+
}
|
83
|
+
|
84
|
+
li .Item span.Shortcut {
|
85
|
+
font-size: max(0.75em, 9px);
|
86
|
+
text-align: right;
|
87
|
+
color: var(--text-subtle);
|
88
|
+
}
|
89
|
+
|
90
|
+
li .Item:not(.Custom):active {
|
91
|
+
scale: 1;
|
92
|
+
}
|
93
|
+
|
94
|
+
li.divider {
|
95
|
+
padding-block: 0.5rem;
|
96
|
+
}
|
97
|
+
|
98
|
+
hr {
|
99
|
+
display: block;
|
100
|
+
border: none;
|
101
|
+
margin: 0;
|
102
|
+
border-top: 1px solid var(--border-color);
|
103
|
+
}
|
104
|
+
|
105
|
+
li:first-child[data-type="item"] {
|
106
|
+
margin-block-start: 0.5rem;
|
107
|
+
}
|
108
|
+
|
109
|
+
li:first-child[data-type="header"]:has(+ li[data-type="item"]) {
|
110
|
+
margin-block-end: 0.5rem;
|
111
|
+
}
|
112
|
+
|
113
|
+
li:nth-last-child(2)[data-type="item"]:has(+ li[data-type="header"]:last-child) {
|
114
|
+
margin-block-end: 0.5rem;
|
115
|
+
}
|
116
|
+
|
117
|
+
@media (pointer: none) {
|
118
|
+
li .Item span.Shortcut {
|
119
|
+
display: none;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
</style>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
2
|
+
import type { MenuItem as Item } from "./MenuTypes.js";
|
3
|
+
declare const __propDef: {
|
4
|
+
props: {
|
5
|
+
item: Item;
|
6
|
+
};
|
7
|
+
events: {
|
8
|
+
[evt: string]: CustomEvent<any>;
|
9
|
+
};
|
10
|
+
slots: {};
|
11
|
+
};
|
12
|
+
export type MenuItemProps = typeof __propDef.props;
|
13
|
+
export type MenuItemEvents = typeof __propDef.events;
|
14
|
+
export type MenuItemSlots = typeof __propDef.slots;
|
15
|
+
export default class MenuItem extends SvelteComponent<MenuItemProps, MenuItemEvents, MenuItemSlots> {
|
16
|
+
}
|
17
|
+
export {};
|
package/dist/nav/MenuTypes.d.ts
CHANGED
@@ -1,11 +1,32 @@
|
|
1
|
+
import type { StatusColorOrString } from "../utils/color.js";
|
1
2
|
import type { ComponentType, Snippet } from "svelte";
|
2
3
|
export type MenuItem = {
|
4
|
+
/** Type of menu item to render. */
|
5
|
+
type: 'divider';
|
6
|
+
} | {
|
7
|
+
/** Type of menu item to render. */
|
8
|
+
type: 'header';
|
3
9
|
/** Text label of the item to display to the user. */
|
4
|
-
|
5
|
-
/**
|
6
|
-
|
10
|
+
content: string | ComponentType | Snippet;
|
11
|
+
/** Color to use for the item. */
|
12
|
+
color?: StatusColorOrString;
|
13
|
+
} | {
|
14
|
+
/** Type of menu item to render. */
|
15
|
+
type: 'item';
|
16
|
+
/** Text label of the item to display to the user. */
|
17
|
+
content: string | ComponentType | Snippet;
|
18
|
+
/** Keyboard shortcut to display next to the item. */
|
19
|
+
shortcut?: string;
|
7
20
|
/** Icon to display. Pass either a Svelte Component or an URL. Use the Icon component to recolor your icons according to the user theme. */
|
8
21
|
icon?: string | ComponentType;
|
22
|
+
/** Path or URL to use for the menu item. */
|
23
|
+
href?: string;
|
24
|
+
/** Click event handler. */
|
25
|
+
onclick?: (event: MouseEvent, item: MenuItem) => void;
|
26
|
+
/** If true, disables the item. */
|
27
|
+
disabled?: boolean;
|
28
|
+
/** Color to use for the item. */
|
29
|
+
color?: StatusColorOrString;
|
9
30
|
/** Menu item children. Pass an array of menu items to create a nested menu. */
|
10
31
|
children?: MenuItem[];
|
11
32
|
};
|