@iyulab/desktop-patterns 0.2.0 → 0.3.1
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/README.md +26 -0
- package/dist/components/shortcut-overlay/dp-shortcut-overlay.d.ts +2 -0
- package/dist/components/sidebar/dp-sidebar.d.ts +43 -5
- package/dist/components/toolbar/dp-toolbar.d.ts +2 -0
- package/dist/decorate-CafwLXg5.js +9 -0
- package/dist/index.js +6 -16
- package/dist/page.js +30 -35
- package/dist/shell.js +38 -40
- package/dist/shortcut-overlay.js +66 -86
- package/dist/sidebar.js +139 -74
- package/dist/toolbar.js +47 -55
- package/package.json +14 -14
package/README.md
CHANGED
|
@@ -59,6 +59,32 @@ document.querySelector('dp-toolbar')!.addEventListener('dp-toolbar-toggle', () =
|
|
|
59
59
|
})
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
### Sidebar items: links, groups, icons, actions
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
nav.items = [
|
|
66
|
+
{ id: 'overview', icon: '■', label: 'Overview', href: '/overview' }, // href → rendered as <a>
|
|
67
|
+
{
|
|
68
|
+
id: 'work', label: 'Work', collapsed: false, // a group: a disclosure over its items
|
|
69
|
+
items: [{ id: 'runs', icon: '▶', label: 'Runs', href: '/runs' }],
|
|
70
|
+
},
|
|
71
|
+
]
|
|
72
|
+
nav.bottomItems = [{ id: 'sign-out', icon: '⎋', label: 'Sign out' }] // actions, not places
|
|
73
|
+
nav.setAttribute('nav-label', 'Main') // names the navigation landmark
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- **`href`** renders the item as a link, so a router's link interception (or the browser) does the navigating.
|
|
77
|
+
`dp-sidebar-select` still fires and is cancelable — `preventDefault()` cancels the navigation and keeps the
|
|
78
|
+
active item. A modified click (Ctrl/⌘/Shift/Alt, middle button) opens the link elsewhere and selects nothing.
|
|
79
|
+
Items without `href` stay buttons and the consumer navigates on `dp-sidebar-select`.
|
|
80
|
+
- **Groups** (`{ id, label, items, icon?, collapsed? }`) render as a named `role="group"` under a disclosure
|
|
81
|
+
button (`aria-expanded`). A group holding the active item is always open. In the collapsed rail every group's
|
|
82
|
+
items show, separated by a rule.
|
|
83
|
+
- **Icons**: each item's icon is a slot named `icon-<id>` whose fallback is the item's `icon` text — slot any icon
|
|
84
|
+
element (`<svg slot="icon-overview">`) to replace it.
|
|
85
|
+
- **Bottom items are actions**: each click fires `dp-sidebar-action` (`itemId`) — every time, so a failed action can
|
|
86
|
+
be retried — and never moves `aria-current`. (In 0.2.x they fired `dp-sidebar-select` and took the active mark.)
|
|
87
|
+
|
|
62
88
|
Every component takes its user-facing text as a plain attribute/property or slot — there is no
|
|
63
89
|
built-in i18n layer. See each component's Storybook story (`npm run storybook`) for its full API.
|
|
64
90
|
|
|
@@ -25,6 +25,8 @@ export declare class DpShortcutOverlay extends LitElement {
|
|
|
25
25
|
open: boolean;
|
|
26
26
|
heading: string;
|
|
27
27
|
emptyMessage: string;
|
|
28
|
+
/** Accessible name of the close button — supply one in the app's language. */
|
|
29
|
+
closeLabel: string;
|
|
28
30
|
private headingId;
|
|
29
31
|
updated(changed: Map<string, unknown>): void;
|
|
30
32
|
disconnectedCallback(): void;
|
|
@@ -1,27 +1,65 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* One navigation entry. With `href` it renders as a link — a router (or the
|
|
4
|
+
* browser) does the navigating, exactly as it would for any other anchor on
|
|
5
|
+
* the page. Without one it renders as a button and the consumer navigates on
|
|
6
|
+
* `dp-sidebar-select`.
|
|
7
|
+
*/
|
|
2
8
|
export interface SidebarItem {
|
|
3
9
|
id: string;
|
|
10
|
+
/** Text fallback for the `icon-<id>` slot. */
|
|
4
11
|
icon: string;
|
|
5
12
|
label: string;
|
|
13
|
+
href?: string;
|
|
14
|
+
}
|
|
15
|
+
/** A named set of items under one disclosure. */
|
|
16
|
+
export interface SidebarGroup {
|
|
17
|
+
id: string;
|
|
18
|
+
/** Text fallback for the `icon-<id>` slot. */
|
|
19
|
+
icon?: string;
|
|
20
|
+
label: string;
|
|
21
|
+
items: SidebarItem[];
|
|
22
|
+
/** Starts closed. A group holding the active item stays open regardless. */
|
|
23
|
+
collapsed?: boolean;
|
|
6
24
|
}
|
|
25
|
+
export type SidebarEntry = SidebarItem | SidebarGroup;
|
|
26
|
+
/**
|
|
27
|
+
* Fired when a navigation item is chosen. Cancelable: calling
|
|
28
|
+
* `preventDefault()` keeps the active item where it was and, for a link,
|
|
29
|
+
* cancels the navigation too.
|
|
30
|
+
*/
|
|
7
31
|
export declare class DpSidebarSelectEvent extends Event {
|
|
8
32
|
readonly itemId: string;
|
|
9
33
|
constructor(itemId: string);
|
|
10
34
|
}
|
|
35
|
+
/** Fired on every click of a bottom item — those are actions, not places. */
|
|
36
|
+
export declare class DpSidebarActionEvent extends Event {
|
|
37
|
+
readonly itemId: string;
|
|
38
|
+
constructor(itemId: string);
|
|
39
|
+
}
|
|
11
40
|
/**
|
|
12
|
-
* App-shell navigation rail: an icon+label list
|
|
13
|
-
* state, an optional pinned
|
|
14
|
-
*
|
|
15
|
-
* string, anything; this
|
|
41
|
+
* App-shell navigation rail: an icon+label list (flat, or grouped under
|
|
42
|
+
* disclosures) with an expanded/collapsed state, an optional pinned group of
|
|
43
|
+
* bottom actions, and a `footer` slot for whatever the consumer wants to
|
|
44
|
+
* anchor at the bottom — a status badge, a version string, anything; this
|
|
45
|
+
* repo doesn't know what.
|
|
46
|
+
*
|
|
47
|
+
* Every item's icon is a slot, `icon-<id>`, whose fallback is the item's
|
|
48
|
+
* `icon` text — so an icon element from any library can stand in for it.
|
|
16
49
|
*/
|
|
17
50
|
export declare class DpSidebar extends LitElement {
|
|
18
51
|
#private;
|
|
19
52
|
static styles: import('lit').CSSResult;
|
|
20
|
-
items:
|
|
53
|
+
items: SidebarEntry[];
|
|
54
|
+
/** Actions, not places — see `DpSidebarActionEvent`. */
|
|
21
55
|
bottomItems: SidebarItem[];
|
|
22
56
|
activeId: string;
|
|
23
57
|
header: string;
|
|
58
|
+
/** Accessible name of the navigation landmark. Unset leaves it unnamed. */
|
|
59
|
+
navLabel: string;
|
|
24
60
|
collapsed: boolean;
|
|
61
|
+
/** Groups whose open/closed state the user has flipped from their `collapsed` default. */
|
|
62
|
+
private toggledGroups;
|
|
25
63
|
render(): import('lit-html').TemplateResult<1>;
|
|
26
64
|
}
|
|
27
65
|
declare global {
|
|
@@ -42,6 +42,8 @@ export declare class DpToolbar extends LitElement {
|
|
|
42
42
|
heading: string;
|
|
43
43
|
subtitle: string;
|
|
44
44
|
showToggle: boolean;
|
|
45
|
+
/** Accessible name of the sidebar toggle — supply one in the app's language. */
|
|
46
|
+
toggleLabel: string;
|
|
45
47
|
dragRegion: boolean;
|
|
46
48
|
connectedCallback(): void;
|
|
47
49
|
render(): import('lit-html').TemplateResult<1>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorate.js
|
|
2
|
+
function e(e, t, n, r) {
|
|
3
|
+
var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
|
|
4
|
+
if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
|
|
5
|
+
else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
|
|
6
|
+
return i > 3 && a && Object.defineProperty(t, n, a), a;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { e as t };
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
|
-
import { DpPage as
|
|
2
|
-
import { DpSidebar as t, DpSidebarSelectEvent as
|
|
3
|
-
import { DpToolbar as
|
|
4
|
-
import { DpShell as
|
|
5
|
-
import { DpShortcutOverlay as
|
|
6
|
-
export {
|
|
7
|
-
o as DpPage,
|
|
8
|
-
v as DpShell,
|
|
9
|
-
b as DpShellSidebarCloseEvent,
|
|
10
|
-
i as DpShortcutOverlay,
|
|
11
|
-
x as DpShortcutOverlayDismissEvent,
|
|
12
|
-
t as DpSidebar,
|
|
13
|
-
l as DpSidebarSelectEvent,
|
|
14
|
-
a as DpToolbar,
|
|
15
|
-
S as DpToolbarToggleEvent
|
|
16
|
-
};
|
|
1
|
+
import { DpPage as e } from "./page.js";
|
|
2
|
+
import { DpSidebar as t, DpSidebarActionEvent as n, DpSidebarSelectEvent as r } from "./sidebar.js";
|
|
3
|
+
import { DpToolbar as i, DpToolbarToggleEvent as a } from "./toolbar.js";
|
|
4
|
+
import { DpShell as o, DpShellSidebarCloseEvent as s } from "./shell.js";
|
|
5
|
+
import { DpShortcutOverlay as c, DpShortcutOverlayDismissEvent as l } from "./shortcut-overlay.js";
|
|
6
|
+
export { e as DpPage, o as DpShell, s as DpShellSidebarCloseEvent, c as DpShortcutOverlay, l as DpShortcutOverlayDismissEvent, t as DpSidebar, n as DpSidebarActionEvent, r as DpSidebarSelectEvent, i as DpToolbar, a as DpToolbarToggleEvent };
|
package/dist/page.js
CHANGED
|
@@ -1,30 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
super(...arguments), this.maxWidth = "md";
|
|
18
|
-
}
|
|
19
|
-
render() {
|
|
20
|
-
return x`
|
|
21
|
-
<div class="inner" style="max-width: ${b[this.maxWidth]}">
|
|
22
|
-
<slot></slot>
|
|
23
|
-
</div>
|
|
24
|
-
`;
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
o.styles = a`
|
|
1
|
+
import { t as e } from "./decorate-CafwLXg5.js";
|
|
2
|
+
import { LitElement as t, css as n, html as r } from "lit";
|
|
3
|
+
import { customElement as i, property as a } from "lit/decorators.js";
|
|
4
|
+
//#region src/components/page/dp-page.ts
|
|
5
|
+
var o = {
|
|
6
|
+
sm: "672px",
|
|
7
|
+
md: "768px",
|
|
8
|
+
lg: "896px",
|
|
9
|
+
xl: "1152px",
|
|
10
|
+
full: "none"
|
|
11
|
+
}, s = class extends t {
|
|
12
|
+
constructor(...e) {
|
|
13
|
+
super(...e), this.maxWidth = "md";
|
|
14
|
+
}
|
|
15
|
+
static {
|
|
16
|
+
this.styles = n`
|
|
28
17
|
:host {
|
|
29
18
|
display: block;
|
|
30
19
|
height: 100%;
|
|
@@ -37,12 +26,18 @@ o.styles = a`
|
|
|
37
26
|
box-sizing: border-box;
|
|
38
27
|
}
|
|
39
28
|
`;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
29
|
+
}
|
|
30
|
+
render() {
|
|
31
|
+
return r`
|
|
32
|
+
<div class="inner" style="max-width: ${o[this.maxWidth]}">
|
|
33
|
+
<slot></slot>
|
|
34
|
+
</div>
|
|
35
|
+
`;
|
|
36
|
+
}
|
|
48
37
|
};
|
|
38
|
+
e([a({
|
|
39
|
+
attribute: "max-width",
|
|
40
|
+
reflect: !0
|
|
41
|
+
})], s.prototype, "maxWidth", void 0), s = e([i("dp-page")], s);
|
|
42
|
+
//#endregion
|
|
43
|
+
export { s as DpPage };
|
package/dist/shell.js
CHANGED
|
@@ -1,34 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return l`
|
|
19
|
-
${this.sidebarOpen ? l`<div class="backdrop" @click=${() => this.dispatchEvent(new v())}></div>` : b}
|
|
20
|
-
<div class="sidebar-region"><slot name="sidebar"></slot></div>
|
|
21
|
-
<div class="main-column">
|
|
22
|
-
<div class="toolbar-row">
|
|
23
|
-
<slot name="toolbar"></slot>
|
|
24
|
-
</div>
|
|
25
|
-
<slot name="banner"></slot>
|
|
26
|
-
<main><slot></slot></main>
|
|
27
|
-
</div>
|
|
28
|
-
`;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
r.styles = p`
|
|
1
|
+
import { t as e } from "./decorate-CafwLXg5.js";
|
|
2
|
+
import { LitElement as t, css as n, html as r, nothing as i } from "lit";
|
|
3
|
+
import { customElement as a, property as o } from "lit/decorators.js";
|
|
4
|
+
//#region src/components/shell/dp-shell.ts
|
|
5
|
+
var s = class extends Event {
|
|
6
|
+
constructor() {
|
|
7
|
+
super("dp-shell-sidebar-close", {
|
|
8
|
+
bubbles: !0,
|
|
9
|
+
composed: !0
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}, c = class extends t {
|
|
13
|
+
constructor(...e) {
|
|
14
|
+
super(...e), this.sidebarOpen = !1;
|
|
15
|
+
}
|
|
16
|
+
static {
|
|
17
|
+
this.styles = n`
|
|
32
18
|
:host {
|
|
33
19
|
display: flex;
|
|
34
20
|
width: 100vw;
|
|
@@ -90,13 +76,25 @@ r.styles = p`
|
|
|
90
76
|
overflow: auto;
|
|
91
77
|
}
|
|
92
78
|
`;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
r =
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
79
|
+
}
|
|
80
|
+
render() {
|
|
81
|
+
return r`
|
|
82
|
+
${this.sidebarOpen ? r`<div class="backdrop" @click=${() => this.dispatchEvent(new s())}></div>` : i}
|
|
83
|
+
<div class="sidebar-region"><slot name="sidebar"></slot></div>
|
|
84
|
+
<div class="main-column">
|
|
85
|
+
<div class="toolbar-row">
|
|
86
|
+
<slot name="toolbar"></slot>
|
|
87
|
+
</div>
|
|
88
|
+
<slot name="banner"></slot>
|
|
89
|
+
<main><slot></slot></main>
|
|
90
|
+
</div>
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
102
93
|
};
|
|
94
|
+
e([o({
|
|
95
|
+
type: Boolean,
|
|
96
|
+
reflect: !0,
|
|
97
|
+
attribute: "sidebar-open"
|
|
98
|
+
})], c.prototype, "sidebarOpen", void 0), c = e([a("dp-shell")], c);
|
|
99
|
+
//#endregion
|
|
100
|
+
export { c as DpShell, s as DpShellSidebarCloseEvent };
|
package/dist/shortcut-overlay.js
CHANGED
|
@@ -1,68 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
updated(e) {
|
|
22
|
-
e.has("open") && (this.open ? window.addEventListener("keydown", u(this, i)) : window.removeEventListener("keydown", u(this, i)));
|
|
23
|
-
}
|
|
24
|
-
disconnectedCallback() {
|
|
25
|
-
super.disconnectedCallback(), window.removeEventListener("keydown", u(this, i));
|
|
26
|
-
}
|
|
27
|
-
render() {
|
|
28
|
-
return this.open ? d`
|
|
29
|
-
<div class="backdrop" @click=${() => f(this, n, p).call(this)}>
|
|
30
|
-
<div
|
|
31
|
-
class="panel"
|
|
32
|
-
role="dialog"
|
|
33
|
-
aria-modal="true"
|
|
34
|
-
aria-labelledby=${this.headingId}
|
|
35
|
-
@click=${(e) => e.stopPropagation()}
|
|
36
|
-
>
|
|
37
|
-
<div class="header">
|
|
38
|
-
<h2 id=${this.headingId}>${this.heading}</h2>
|
|
39
|
-
<button class="close" aria-label="Close" @click=${() => f(this, n, p).call(this)}>×</button>
|
|
40
|
-
</div>
|
|
41
|
-
<div class="body">
|
|
42
|
-
${this.shortcuts.length === 0 ? d`<p class="empty">${this.emptyMessage}</p>` : d`
|
|
43
|
-
<ul>
|
|
44
|
-
${this.shortcuts.map(
|
|
45
|
-
(e) => d`
|
|
46
|
-
<li>
|
|
47
|
-
<span>${e.description}</span>
|
|
48
|
-
<kbd>${e.combo}</kbd>
|
|
49
|
-
</li>
|
|
50
|
-
`
|
|
51
|
-
)}
|
|
52
|
-
</ul>
|
|
53
|
-
`}
|
|
54
|
-
</div>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
` : w;
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
i = /* @__PURE__ */ new WeakMap();
|
|
61
|
-
n = /* @__PURE__ */ new WeakSet();
|
|
62
|
-
p = function() {
|
|
63
|
-
this.dispatchEvent(new z());
|
|
64
|
-
};
|
|
65
|
-
o.styles = x`
|
|
1
|
+
import { t as e } from "./decorate-CafwLXg5.js";
|
|
2
|
+
import { LitElement as t, css as n, html as r, nothing as i } from "lit";
|
|
3
|
+
import { customElement as a, property as o, state as s } from "lit/decorators.js";
|
|
4
|
+
//#region src/components/shortcut-overlay/dp-shortcut-overlay.ts
|
|
5
|
+
var c = class extends Event {
|
|
6
|
+
constructor() {
|
|
7
|
+
super("dp-shortcut-overlay-dismiss", {
|
|
8
|
+
bubbles: !0,
|
|
9
|
+
composed: !0
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}, l = 0, u = class extends t {
|
|
13
|
+
constructor(...e) {
|
|
14
|
+
super(...e), this.shortcuts = [], this.open = !1, this.heading = "Keyboard shortcuts", this.emptyMessage = "No shortcuts registered.", this.closeLabel = "Close", this.headingId = `dp-shortcut-overlay-heading-${++l}`, this.#e = (e) => {
|
|
15
|
+
e.key === "Escape" && (e.preventDefault(), this.#t());
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
static {
|
|
19
|
+
this.styles = n`
|
|
66
20
|
:host {
|
|
67
21
|
display: contents;
|
|
68
22
|
font-family: var(--dc-font-family, system-ui, sans-serif);
|
|
@@ -148,25 +102,51 @@ o.styles = x`
|
|
|
148
102
|
font-size: 10px;
|
|
149
103
|
}
|
|
150
104
|
`;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
105
|
+
}
|
|
106
|
+
#e;
|
|
107
|
+
updated(e) {
|
|
108
|
+
e.has("open") && (this.open ? window.addEventListener("keydown", this.#e) : window.removeEventListener("keydown", this.#e));
|
|
109
|
+
}
|
|
110
|
+
disconnectedCallback() {
|
|
111
|
+
super.disconnectedCallback(), window.removeEventListener("keydown", this.#e);
|
|
112
|
+
}
|
|
113
|
+
#t() {
|
|
114
|
+
this.dispatchEvent(new c());
|
|
115
|
+
}
|
|
116
|
+
render() {
|
|
117
|
+
return this.open ? r`
|
|
118
|
+
<div class="backdrop" @click=${() => this.#t()}>
|
|
119
|
+
<div
|
|
120
|
+
class="panel"
|
|
121
|
+
role="dialog"
|
|
122
|
+
aria-modal="true"
|
|
123
|
+
aria-labelledby=${this.headingId}
|
|
124
|
+
@click=${(e) => e.stopPropagation()}
|
|
125
|
+
>
|
|
126
|
+
<div class="header">
|
|
127
|
+
<h2 id=${this.headingId}>${this.heading}</h2>
|
|
128
|
+
<button class="close" aria-label=${this.closeLabel} @click=${() => this.#t()}>×</button>
|
|
129
|
+
</div>
|
|
130
|
+
<div class="body">
|
|
131
|
+
${this.shortcuts.length === 0 ? r`<p class="empty">${this.emptyMessage}</p>` : r`
|
|
132
|
+
<ul>
|
|
133
|
+
${this.shortcuts.map((e) => r`
|
|
134
|
+
<li>
|
|
135
|
+
<span>${e.description}</span>
|
|
136
|
+
<kbd>${e.combo}</kbd>
|
|
137
|
+
</li>
|
|
138
|
+
`)}
|
|
139
|
+
</ul>
|
|
140
|
+
`}
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
` : i;
|
|
145
|
+
}
|
|
172
146
|
};
|
|
147
|
+
e([o({ type: Array })], u.prototype, "shortcuts", void 0), e([o({
|
|
148
|
+
type: Boolean,
|
|
149
|
+
reflect: !0
|
|
150
|
+
})], u.prototype, "open", void 0), e([o()], u.prototype, "heading", void 0), e([o({ attribute: "empty-message" })], u.prototype, "emptyMessage", void 0), e([o({ attribute: "close-label" })], u.prototype, "closeLabel", void 0), e([s()], u.prototype, "headingId", void 0), u = e([a("dp-shortcut-overlay")], u);
|
|
151
|
+
//#endregion
|
|
152
|
+
export { u as DpShortcutOverlay, c as DpShortcutOverlayDismissEvent };
|
package/dist/sidebar.js
CHANGED
|
@@ -1,51 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
${this.bottomItems.length > 0 ? i`<div class="bottom-group">${this.bottomItems.map((e) => v(this, n, f).call(this, e))}</div>` : c}
|
|
27
|
-
<div class="footer"><slot name="footer"></slot></div>
|
|
28
|
-
`;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
n = /* @__PURE__ */ new WeakSet();
|
|
32
|
-
f = function(e) {
|
|
33
|
-
const t = e.id === this.activeId;
|
|
34
|
-
return i`
|
|
35
|
-
<button
|
|
36
|
-
title=${this.collapsed ? e.label : c}
|
|
37
|
-
aria-current=${t ? "page" : c}
|
|
38
|
-
@click=${() => v(this, n, u).call(this, e.id)}
|
|
39
|
-
>
|
|
40
|
-
<span class="icon" aria-hidden="true">${e.icon}</span>
|
|
41
|
-
${this.collapsed ? c : i`<span>${e.label}</span>`}
|
|
42
|
-
</button>
|
|
43
|
-
`;
|
|
44
|
-
};
|
|
45
|
-
u = function(e) {
|
|
46
|
-
e !== this.activeId && (this.activeId = e, this.dispatchEvent(new $(e)));
|
|
47
|
-
};
|
|
48
|
-
r.styles = m`
|
|
1
|
+
import { t as e } from "./decorate-CafwLXg5.js";
|
|
2
|
+
import { LitElement as t, css as n, html as r, nothing as i } from "lit";
|
|
3
|
+
import { customElement as a, property as o, state as s } from "lit/decorators.js";
|
|
4
|
+
//#region src/components/sidebar/dp-sidebar.ts
|
|
5
|
+
var c = (e) => Array.isArray(e.items), l = class extends Event {
|
|
6
|
+
constructor(e) {
|
|
7
|
+
super("dp-sidebar-select", {
|
|
8
|
+
bubbles: !0,
|
|
9
|
+
composed: !0,
|
|
10
|
+
cancelable: !0
|
|
11
|
+
}), this.itemId = e;
|
|
12
|
+
}
|
|
13
|
+
}, u = class extends Event {
|
|
14
|
+
constructor(e) {
|
|
15
|
+
super("dp-sidebar-action", {
|
|
16
|
+
bubbles: !0,
|
|
17
|
+
composed: !0
|
|
18
|
+
}), this.itemId = e;
|
|
19
|
+
}
|
|
20
|
+
}, d = class extends t {
|
|
21
|
+
constructor(...e) {
|
|
22
|
+
super(...e), this.items = [], this.bottomItems = [], this.activeId = "", this.header = "", this.navLabel = "", this.collapsed = !1, this.toggledGroups = /* @__PURE__ */ new Set();
|
|
23
|
+
}
|
|
24
|
+
static {
|
|
25
|
+
this.styles = n`
|
|
49
26
|
:host {
|
|
50
27
|
display: flex;
|
|
51
28
|
flex-direction: column;
|
|
@@ -89,11 +66,12 @@ r.styles = m`
|
|
|
89
66
|
border-top: 1px solid var(--dc-color-border, #e2e2e4);
|
|
90
67
|
padding: var(--dc-space-1, 4px) 0;
|
|
91
68
|
}
|
|
92
|
-
|
|
69
|
+
.item {
|
|
93
70
|
appearance: none;
|
|
94
71
|
background: none;
|
|
95
72
|
border: none;
|
|
96
73
|
border-left: 2px solid transparent;
|
|
74
|
+
box-sizing: border-box;
|
|
97
75
|
width: 100%;
|
|
98
76
|
display: flex;
|
|
99
77
|
align-items: center;
|
|
@@ -103,12 +81,23 @@ r.styles = m`
|
|
|
103
81
|
font-size: var(--dc-font-size-sm, 12px);
|
|
104
82
|
color: var(--dc-color-text-secondary, #55555c);
|
|
105
83
|
text-align: left;
|
|
84
|
+
text-decoration: none;
|
|
106
85
|
cursor: pointer;
|
|
107
86
|
}
|
|
108
|
-
:host([collapsed])
|
|
87
|
+
:host([collapsed]) .item {
|
|
109
88
|
justify-content: center;
|
|
110
89
|
padding: var(--dc-space-3, 12px) 0;
|
|
111
90
|
}
|
|
91
|
+
/* Items inside an open group sit one step in, so the group reads as a set. */
|
|
92
|
+
:host(:not([collapsed])) .group-items .item {
|
|
93
|
+
padding-left: calc(var(--dc-space-3, 12px) * 2);
|
|
94
|
+
}
|
|
95
|
+
/* In the collapsed rail a group has no label to show; a rule marks where it starts. */
|
|
96
|
+
:host([collapsed]) .group + .group,
|
|
97
|
+
:host([collapsed]) .item + .group,
|
|
98
|
+
:host([collapsed]) .group + .item {
|
|
99
|
+
border-top: 1px solid var(--dc-color-border, #e2e2e4);
|
|
100
|
+
}
|
|
112
101
|
/* The rail marker keeps the fill accent - it is a 3px bar, judged as a UI
|
|
113
102
|
component (WCAG 1.4.11, 3:1). The label does not: an accent chosen to be
|
|
114
103
|
read as a *fill* is not necessarily readable as 12px text on the hover
|
|
@@ -118,15 +107,15 @@ r.styles = m`
|
|
|
118
107
|
find. --dc-color-accent-text lets a consumer supply the readable
|
|
119
108
|
variant; falling back to the fill accent keeps every existing consumer
|
|
120
109
|
rendering exactly as before. */
|
|
121
|
-
|
|
110
|
+
.item[aria-current='page'] {
|
|
122
111
|
border-left-color: var(--dc-color-accent, #2563eb);
|
|
123
112
|
color: var(--dc-color-accent-text, var(--dc-color-accent, #2563eb));
|
|
124
113
|
font-weight: var(--dc-font-weight-medium, 500);
|
|
125
114
|
}
|
|
126
|
-
|
|
115
|
+
.item:hover {
|
|
127
116
|
background: var(--dc-color-surface-hover, #ececed);
|
|
128
117
|
}
|
|
129
|
-
|
|
118
|
+
.item:focus-visible {
|
|
130
119
|
outline: 2px solid var(--dc-color-accent, #2563eb);
|
|
131
120
|
outline-offset: -2px;
|
|
132
121
|
}
|
|
@@ -135,29 +124,105 @@ r.styles = m`
|
|
|
135
124
|
width: 1.25em;
|
|
136
125
|
text-align: center;
|
|
137
126
|
}
|
|
127
|
+
.caret {
|
|
128
|
+
margin-left: auto;
|
|
129
|
+
transition: transform 0.15s;
|
|
130
|
+
}
|
|
131
|
+
.group-toggle[aria-expanded='false'] .caret {
|
|
132
|
+
transform: rotate(-90deg);
|
|
133
|
+
}
|
|
138
134
|
.footer {
|
|
139
135
|
border-top: 1px solid var(--dc-color-border, #e2e2e4);
|
|
140
136
|
}
|
|
141
137
|
`;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
138
|
+
}
|
|
139
|
+
render() {
|
|
140
|
+
return r`
|
|
141
|
+
<div class="header">
|
|
142
|
+
<slot name="icon"></slot>
|
|
143
|
+
${!this.collapsed && this.header ? r`<span class="header-label">${this.header}</span>` : i}
|
|
144
|
+
</div>
|
|
145
|
+
<nav aria-label=${this.navLabel || i}>
|
|
146
|
+
${this.items.map((e) => c(e) ? this.#e(e) : this.#t(e))}
|
|
147
|
+
</nav>
|
|
148
|
+
${this.bottomItems.length > 0 ? r`<div class="bottom-group">${this.bottomItems.map((e) => this.#n(e))}</div>` : i}
|
|
149
|
+
<div class="footer"><slot name="footer"></slot></div>
|
|
150
|
+
`;
|
|
151
|
+
}
|
|
152
|
+
#e(e) {
|
|
153
|
+
let t = e.items.some((e) => e.id === this.activeId), n = e.collapsed === !0, a = this.collapsed || t || n === this.toggledGroups.has(e.id), o = `group-${e.id}`;
|
|
154
|
+
return r`
|
|
155
|
+
<div class="group">
|
|
156
|
+
${this.collapsed ? i : r`<button
|
|
157
|
+
class="item group-toggle"
|
|
158
|
+
aria-expanded=${a ? "true" : "false"}
|
|
159
|
+
aria-controls=${o}
|
|
160
|
+
@click=${() => this.#a(e.id)}
|
|
161
|
+
>
|
|
162
|
+
${this.#r(e.id, e.icon ?? "")}
|
|
163
|
+
<span class="label">${e.label}</span>
|
|
164
|
+
<span class="caret" aria-hidden="true">▾</span>
|
|
165
|
+
</button>`}
|
|
166
|
+
<div class="group-items" id=${o} role="group" aria-label=${e.label} ?hidden=${!a}>
|
|
167
|
+
${e.items.map((e) => this.#t(e))}
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
`;
|
|
171
|
+
}
|
|
172
|
+
#t(e) {
|
|
173
|
+
let t = e.id === this.activeId, n = r`
|
|
174
|
+
${this.#r(e.id, e.icon)} ${this.collapsed ? i : r`<span class="label">${e.label}</span>`}
|
|
175
|
+
`;
|
|
176
|
+
return e.href === void 0 ? r`<button
|
|
177
|
+
class="item"
|
|
178
|
+
title=${this.collapsed ? e.label : i}
|
|
179
|
+
aria-current=${t ? "page" : i}
|
|
180
|
+
@click=${(t) => this.#i(t, e)}
|
|
181
|
+
>
|
|
182
|
+
${n}
|
|
183
|
+
</button>` : r`<a
|
|
184
|
+
class="item"
|
|
185
|
+
href=${e.href}
|
|
186
|
+
title=${this.collapsed ? e.label : i}
|
|
187
|
+
aria-current=${t ? "page" : i}
|
|
188
|
+
@click=${(t) => this.#i(t, e)}
|
|
189
|
+
>${n}</a
|
|
190
|
+
>`;
|
|
191
|
+
}
|
|
192
|
+
#n(e) {
|
|
193
|
+
return r`
|
|
194
|
+
<button
|
|
195
|
+
class="item"
|
|
196
|
+
title=${this.collapsed ? e.label : i}
|
|
197
|
+
@click=${() => this.dispatchEvent(new u(e.id))}
|
|
198
|
+
>
|
|
199
|
+
${this.#r(e.id, e.icon)} ${this.collapsed ? i : r`<span class="label">${e.label}</span>`}
|
|
200
|
+
</button>
|
|
201
|
+
`;
|
|
202
|
+
}
|
|
203
|
+
#r(e, t) {
|
|
204
|
+
return r`<span class="icon" aria-hidden="true"><slot name=${`icon-${e}`}>${t}</slot></span>`;
|
|
205
|
+
}
|
|
206
|
+
#i(e, t) {
|
|
207
|
+
if (!(t.href !== void 0 && (e.button !== 0 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey)) && t.id !== this.activeId) {
|
|
208
|
+
if (!this.dispatchEvent(new l(t.id))) {
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
this.activeId = t.id;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
#a(e) {
|
|
216
|
+
let t = new Set(this.toggledGroups);
|
|
217
|
+
t.delete(e) || t.add(e), this.toggledGroups = t;
|
|
218
|
+
}
|
|
163
219
|
};
|
|
220
|
+
e([o({ type: Array })], d.prototype, "items", void 0), e([o({
|
|
221
|
+
type: Array,
|
|
222
|
+
attribute: "bottom-items"
|
|
223
|
+
})], d.prototype, "bottomItems", void 0), e([o({ attribute: "active-id" })], d.prototype, "activeId", void 0), e([o()], d.prototype, "header", void 0), e([o({ attribute: "nav-label" })], d.prototype, "navLabel", void 0), e([o({
|
|
224
|
+
type: Boolean,
|
|
225
|
+
reflect: !0
|
|
226
|
+
})], d.prototype, "collapsed", void 0), e([s()], d.prototype, "toggledGroups", void 0), d = e([a("dp-sidebar")], d);
|
|
227
|
+
//#endregion
|
|
228
|
+
export { d as DpSidebar, u as DpSidebarActionEvent, l as DpSidebarSelectEvent };
|
package/dist/toolbar.js
CHANGED
|
@@ -1,40 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
super.connectedCallback(), this.setAttribute("role", "banner");
|
|
19
|
-
}
|
|
20
|
-
render() {
|
|
21
|
-
return d`
|
|
22
|
-
<div class="start">
|
|
23
|
-
${this.showToggle ? d`<button
|
|
24
|
-
class="toggle"
|
|
25
|
-
aria-label="Toggle sidebar"
|
|
26
|
-
@click=${() => this.dispatchEvent(new u())}
|
|
27
|
-
>
|
|
28
|
-
☰
|
|
29
|
-
</button>` : h}
|
|
30
|
-
<span class="title">${this.subtitle || this.heading}</span>
|
|
31
|
-
</div>
|
|
32
|
-
<div class="drag-handle" part="drag-handle"></div>
|
|
33
|
-
<div class="actions"><slot name="actions"></slot></div>
|
|
34
|
-
`;
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
t.styles = p`
|
|
1
|
+
import { t as e } from "./decorate-CafwLXg5.js";
|
|
2
|
+
import { LitElement as t, css as n, html as r, nothing as i } from "lit";
|
|
3
|
+
import { customElement as a, property as o } from "lit/decorators.js";
|
|
4
|
+
//#region src/components/toolbar/dp-toolbar.ts
|
|
5
|
+
var s = class extends Event {
|
|
6
|
+
constructor() {
|
|
7
|
+
super("dp-toolbar-toggle", {
|
|
8
|
+
bubbles: !0,
|
|
9
|
+
composed: !0
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}, c = class extends t {
|
|
13
|
+
constructor(...e) {
|
|
14
|
+
super(...e), this.heading = "", this.subtitle = "", this.showToggle = !1, this.toggleLabel = "Toggle sidebar", this.dragRegion = !1;
|
|
15
|
+
}
|
|
16
|
+
static {
|
|
17
|
+
this.styles = n`
|
|
38
18
|
:host {
|
|
39
19
|
display: flex;
|
|
40
20
|
align-items: center;
|
|
@@ -90,22 +70,34 @@ t.styles = p`
|
|
|
90
70
|
gap: var(--dc-space-3, 12px);
|
|
91
71
|
}
|
|
92
72
|
`;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
73
|
+
}
|
|
74
|
+
connectedCallback() {
|
|
75
|
+
super.connectedCallback(), this.setAttribute("role", "banner");
|
|
76
|
+
}
|
|
77
|
+
render() {
|
|
78
|
+
return r`
|
|
79
|
+
<div class="start">
|
|
80
|
+
${this.showToggle ? r`<button
|
|
81
|
+
class="toggle"
|
|
82
|
+
aria-label=${this.toggleLabel}
|
|
83
|
+
@click=${() => this.dispatchEvent(new s())}
|
|
84
|
+
>
|
|
85
|
+
☰
|
|
86
|
+
</button>` : i}
|
|
87
|
+
<span class="title">${this.subtitle || this.heading}</span>
|
|
88
|
+
</div>
|
|
89
|
+
<div class="drag-handle" part="drag-handle"></div>
|
|
90
|
+
<div class="actions"><slot name="actions"></slot></div>
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
111
93
|
};
|
|
94
|
+
e([o()], c.prototype, "heading", void 0), e([o()], c.prototype, "subtitle", void 0), e([o({
|
|
95
|
+
type: Boolean,
|
|
96
|
+
attribute: "show-toggle"
|
|
97
|
+
})], c.prototype, "showToggle", void 0), e([o({ attribute: "toggle-label" })], c.prototype, "toggleLabel", void 0), e([o({
|
|
98
|
+
type: Boolean,
|
|
99
|
+
reflect: !0,
|
|
100
|
+
attribute: "drag-region"
|
|
101
|
+
})], c.prototype, "dragRegion", void 0), c = e([a("dp-toolbar")], c);
|
|
102
|
+
//#endregion
|
|
103
|
+
export { c as DpToolbar, s as DpToolbarToggleEvent };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/desktop-patterns",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -57,23 +57,23 @@
|
|
|
57
57
|
"build-storybook": "storybook build"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"lit": "^3.
|
|
60
|
+
"lit": "^3.3.3"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"@iyulab/desktop-compact": "^0.2.0 || ^0.3.0"
|
|
63
|
+
"@iyulab/desktop-compact": "^0.2.0 || ^0.3.0 || ^0.4.0 || ^0.5.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@iyulab/desktop-compact": "^0.
|
|
67
|
-
"@open-wc/testing": "^
|
|
68
|
-
"@storybook/
|
|
69
|
-
"@storybook/web-components": "^
|
|
70
|
-
"@storybook/web-components-vite": "^8.3.0",
|
|
66
|
+
"@iyulab/desktop-compact": "^0.5.0",
|
|
67
|
+
"@open-wc/testing": "^5.0.0",
|
|
68
|
+
"@storybook/web-components": "^10.6.0",
|
|
69
|
+
"@storybook/web-components-vite": "^10.6.0",
|
|
71
70
|
"@types/mocha": "^10.0.10",
|
|
72
|
-
"@web/dev-server-esbuild": "^
|
|
73
|
-
"@web/test-runner": "^0.
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"vite
|
|
71
|
+
"@web/dev-server-esbuild": "^2.0.0",
|
|
72
|
+
"@web/test-runner": "^1.0.0",
|
|
73
|
+
"axe-core": "^4.13.0",
|
|
74
|
+
"storybook": "^10.6.0",
|
|
75
|
+
"typescript": "^6.0.3",
|
|
76
|
+
"vite": "^8.3.1",
|
|
77
|
+
"vite-plugin-dts": "^5.1.1"
|
|
78
78
|
}
|
|
79
79
|
}
|