@iyulab/desktop-patterns 0.4.0 → 0.6.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/README.md +53 -13
- package/dist/breakpoints.d.ts +2 -2
- package/dist/{breakpoints-BjS_v3PV.js → breakpoints.js} +1 -1
- package/dist/components/list-detail/dp-list-detail.d.ts +25 -0
- package/dist/components/shortcut-overlay/dp-shortcut-overlay.d.ts +3 -1
- package/dist/components/sidebar/dp-sidebar.d.ts +10 -0
- package/dist/components/toolbar/dp-toolbar.d.ts +5 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -6
- package/dist/list-detail.js +65 -0
- package/dist/shell.js +1 -1
- package/dist/shortcut-overlay.js +16 -7
- package/dist/sidebar.js +21 -11
- package/dist/toolbar.js +16 -23
- package/package.json +12 -1
- package/tokens.css +2 -0
package/README.md
CHANGED
|
@@ -51,22 +51,58 @@ document.querySelector<HTMLElementTagNameMap['dp-sidebar']>('#nav')!.items = [
|
|
|
51
51
|
{ id: 'overview', icon: '■', label: 'Overview' },
|
|
52
52
|
]
|
|
53
53
|
|
|
54
|
+
import { desktopMinWidth } from '@iyulab/desktop-patterns/breakpoints' // no elements registered
|
|
55
|
+
|
|
54
56
|
const shell = document.querySelector('dp-shell')!
|
|
55
|
-
document.querySelector('dp-sidebar')
|
|
57
|
+
const sidebar = document.querySelector('dp-sidebar')!
|
|
58
|
+
const toolbar = document.querySelector('dp-toolbar')!
|
|
59
|
+
const wide = matchMedia(`(min-width: ${desktopMinWidth}px)`)
|
|
60
|
+
let collapsed = false // the consumer's own state: a wide window's sidebar folded to its rail
|
|
61
|
+
|
|
62
|
+
function sync() {
|
|
63
|
+
sidebar.collapsed = collapsed && wide.matches // a drawer always shows the whole sidebar
|
|
64
|
+
toolbar.expanded = wide.matches ? !collapsed : shell.sidebarOpen
|
|
65
|
+
}
|
|
66
|
+
wide.addEventListener('change', sync)
|
|
67
|
+
sidebar.addEventListener('dp-sidebar-select', () => {
|
|
56
68
|
// consumer owns activeId / routing
|
|
57
|
-
shell.sidebarOpen = false // a drawer gives way to what was picked
|
|
58
69
|
})
|
|
59
|
-
|
|
60
|
-
shell.sidebarOpen =
|
|
70
|
+
sidebar.addEventListener('dp-sidebar-activate', () => {
|
|
71
|
+
shell.sidebarOpen = false // a drawer gives way to what was picked — the place already shown included
|
|
72
|
+
sync()
|
|
61
73
|
})
|
|
62
|
-
|
|
74
|
+
toolbar.addEventListener('dp-toolbar-toggle', () => {
|
|
75
|
+
if (wide.matches) collapsed = !collapsed
|
|
76
|
+
else shell.sidebarOpen = !shell.sidebarOpen
|
|
77
|
+
sync()
|
|
78
|
+
})
|
|
79
|
+
shell.addEventListener('dp-shell-sidebar-close', () => { shell.sidebarOpen = false; sync() }) // backdrop, Escape
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Below the desktop breakpoint (`desktopMinWidth`, 1024px — `desktopMedia` for a component's styles)
|
|
83
|
+
the sidebar is a drawer over the content, open while `sidebar-open` is set; at and above it the
|
|
84
|
+
sidebar sits beside the content and `sidebar-open` changes nothing. The same toolbar toggle serves
|
|
85
|
+
both widths: in a narrow window it opens the drawer, in a wide one it folds the sidebar to its
|
|
86
|
+
collapsed rail (`dp-sidebar` `collapsed`). Give the toggle `expanded` so assistive technology hears
|
|
87
|
+
which state it is in. The consumer owns both states — start the drawer closed, close it when the
|
|
88
|
+
shell asks (backdrop click, Escape) and when a place is picked, or a narrow window stays covered.
|
|
89
|
+
|
|
90
|
+
### A list beside the item picked from it
|
|
91
|
+
|
|
92
|
+
```html
|
|
93
|
+
<dp-page fill max-width="full">
|
|
94
|
+
<dp-list-detail>
|
|
95
|
+
<nav slot="list" aria-label="People">…</nav>
|
|
96
|
+
<article>…the person picked…</article>
|
|
97
|
+
</dp-list-detail>
|
|
98
|
+
</dp-page>
|
|
63
99
|
```
|
|
64
100
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
101
|
+
`dp-list-detail` puts the `list` slot beside the default slot, each scrolling on its own, the list
|
|
102
|
+
`--dp-list-detail-list-width` wide (by default the sidebar's width — navigation, list and item read as
|
|
103
|
+
1:1:rest). Below the desktop breakpoint there is room for one pane: the item while `detail-open` is
|
|
104
|
+
set, the list otherwise. The consumer owns `detail-open` — set it when an item is picked, and give
|
|
105
|
+
the item a way back that clears it, shown only below `desktopMinWidth`.
|
|
70
106
|
|
|
71
107
|
### Sidebar items: links, groups, icons, actions
|
|
72
108
|
|
|
@@ -91,6 +127,9 @@ nav.setAttribute('nav-label', 'Main') // names t
|
|
|
91
127
|
items show, separated by a rule.
|
|
92
128
|
- **Icons**: each item's icon is a slot named `icon-<id>` whose fallback is the item's `icon` text — slot any icon
|
|
93
129
|
element (`<svg slot="icon-overview">`) to replace it.
|
|
130
|
+
- **`dp-sidebar-activate`** fires on every pick of a navigation item, the active one included (after
|
|
131
|
+
`dp-sidebar-select` when the place changes; not when that was cancelled). Close a drawer on it: picking the
|
|
132
|
+
place already shown still means "take me there", and `dp-sidebar-select` does not fire for it.
|
|
94
133
|
- **Bottom items are actions**: each click fires `dp-sidebar-action` (`itemId`) — every time, so a failed action can
|
|
95
134
|
be retried — and never moves `aria-current`. (In 0.2.x they fired `dp-sidebar-select` and took the active mark.)
|
|
96
135
|
|
|
@@ -108,7 +147,7 @@ import '@iyulab/desktop-patterns/tokens.css'
|
|
|
108
147
|
|
|
109
148
|
Color/spacing/radius/typography all come from `desktop-compact`'s `--dc-*` tokens — this package adds
|
|
110
149
|
only the structural dimensions `desktop-compact` has no concept of (`--dp-sidebar-width`,
|
|
111
|
-
`--dp-sidebar-width-collapsed`, `--dp-header-height`). Every component ships with sane fallback
|
|
150
|
+
`--dp-sidebar-width-collapsed`, `--dp-header-height`, `--dp-list-detail-list-width`). Every component ships with sane fallback
|
|
112
151
|
values, so it still renders correctly even without either stylesheet.
|
|
113
152
|
|
|
114
153
|
## Platform boundary — drag regions
|
|
@@ -130,13 +169,14 @@ dp-toolbar[drag-region]::part(drag-handle) {
|
|
|
130
169
|
`toolbar`, so ownership of the drag handle stays entirely with whatever renders there (typically
|
|
131
170
|
`dp-toolbar`).
|
|
132
171
|
|
|
133
|
-
## Components
|
|
172
|
+
## Components
|
|
134
173
|
|
|
135
174
|
| Component | Description |
|
|
136
175
|
|---|---|
|
|
137
176
|
| `dp-page` | Scrollable content region with a centered, max-width column — the page-body every view renders into. With `fill` it does not scroll and its column is as tall as the region, for a view that scrolls its own parts (a list beside the item open) |
|
|
177
|
+
| `dp-list-detail` | A list beside the item picked from it (master-detail) — each pane scrolls on its own; one pane at a time below 1024px, the item while `detail-open` is set |
|
|
138
178
|
| `dp-sidebar` | App-shell navigation rail — expanded/collapsed states, an optional pinned bottom group, a `footer` slot for whatever a consumer wants to anchor there |
|
|
139
|
-
| `dp-toolbar` | App-shell header bar — `heading`/`subtitle`, an optional sidebar
|
|
179
|
+
| `dp-toolbar` | App-shell header bar — `heading`/`subtitle`, an optional sidebar toggle (drawer in a narrow window, collapse in a wide one), a right-side `actions` slot |
|
|
140
180
|
| `dp-shell` | Top-level layout composing `sidebar`/`toolbar`/`banner`/main-content regions, with a responsive drawer (backdrop + overlay sidebar) below a 1024px breakpoint |
|
|
141
181
|
| `dp-shortcut-overlay` | Display-only keyboard-shortcuts help panel — a `shortcuts` list + `open` flag; no registration/binding infrastructure (that stays the consumer's) |
|
|
142
182
|
|
package/dist/breakpoints.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The desktop breakpoint, in CSS pixels. Below it `dp-shell`'s sidebar is a drawer over the
|
|
3
|
-
* content; at and above it the sidebar
|
|
4
|
-
*
|
|
3
|
+
* content; at and above it the sidebar sits beside the content, where a consumer may fold
|
|
4
|
+
* `dp-sidebar` to its collapsed rail instead.
|
|
5
5
|
*/
|
|
6
6
|
export declare const desktopMinWidth = 1024;
|
|
7
7
|
/** The media query for {@link desktopMinWidth}, for a component's styles. */
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* A list beside the item picked from it — the master-detail view of mail, files or records. The
|
|
4
|
+
* `list` slot holds what to pick from, the default slot what was picked. Each pane scrolls on its
|
|
5
|
+
* own, so the list stays where it was while the item is read.
|
|
6
|
+
*
|
|
7
|
+
* At desktop width the list sits at the start, `--dp-list-detail-list-width` wide (by default the
|
|
8
|
+
* sidebar's width, so navigation and list line up as equal columns), and the item takes the rest.
|
|
9
|
+
* Below it there is room for one pane: the item while `detail-open` is set, the list otherwise. The
|
|
10
|
+
* consumer owns `detail-open` — set it when an item is picked and clear it to go back to the list
|
|
11
|
+
* (a back control in the item, which it shows only while narrow).
|
|
12
|
+
*
|
|
13
|
+
* Give the view a definite height — inside `dp-page fill`, or any box with one.
|
|
14
|
+
*/
|
|
15
|
+
export declare class DpListDetail extends LitElement {
|
|
16
|
+
static styles: import('lit').CSSResult;
|
|
17
|
+
/** Below desktop width, show the picked item instead of the list. Above it both are always shown. */
|
|
18
|
+
detailOpen: boolean;
|
|
19
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
20
|
+
}
|
|
21
|
+
declare global {
|
|
22
|
+
interface HTMLElementTagNameMap {
|
|
23
|
+
'dp-list-detail': DpListDetail;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -13,7 +13,9 @@ export declare class DpShortcutOverlayDismissEvent extends Event {
|
|
|
13
13
|
* `shift+/` shortcut and read from a module-level, framework-hook-specific
|
|
14
14
|
* registry; both are the consumer's responsibility here (see
|
|
15
15
|
* docs/superpowers/specs/2026-09-02-desktop-patterns-design.md, the
|
|
16
|
-
* dp-shortcut-overlay row).
|
|
16
|
+
* dp-shortcut-overlay row). While open it is a modal dialog: focus moves to
|
|
17
|
+
* its close button, Tab stays inside it, and focus goes back where it was once
|
|
18
|
+
* it closes. This component only dismisses itself (outside
|
|
17
19
|
* click / Escape) by asking — it dispatches `dp-shortcut-overlay-dismiss`
|
|
18
20
|
* rather than setting its own `open` to false, since `open` is the
|
|
19
21
|
* consumer's state to own, not this component's.
|
|
@@ -32,6 +32,16 @@ export declare class DpSidebarSelectEvent extends Event {
|
|
|
32
32
|
readonly itemId: string;
|
|
33
33
|
constructor(itemId: string);
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Fired whenever a navigation item is picked, the active one included — after `dp-sidebar-select`
|
|
37
|
+
* when the place changes, alone when the item picked is the one already active. Not cancelable.
|
|
38
|
+
* It is the moment a drawer holding the sidebar gives way: picking the place already shown still
|
|
39
|
+
* means "take me there".
|
|
40
|
+
*/
|
|
41
|
+
export declare class DpSidebarActivateEvent extends Event {
|
|
42
|
+
readonly itemId: string;
|
|
43
|
+
constructor(itemId: string);
|
|
44
|
+
}
|
|
35
45
|
/** Fired on every click of a bottom item — those are actions, not places. */
|
|
36
46
|
export declare class DpSidebarActionEvent extends Event {
|
|
37
47
|
readonly itemId: string;
|
|
@@ -4,9 +4,9 @@ export declare class DpToolbarToggleEvent extends Event {
|
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
6
6
|
* App-shell header bar: a `heading` (optionally overridden per-view by
|
|
7
|
-
* `subtitle`), an optional toggle
|
|
8
|
-
*
|
|
9
|
-
* right-side `actions` slot. Pure layout — this repo does not call any platform API.
|
|
7
|
+
* `subtitle`), an optional sidebar toggle — the consumer decides what it does
|
|
8
|
+
* (open `dp-shell`'s drawer in a narrow window, fold `dp-sidebar` to its rail
|
|
9
|
+
* in a wide one) — and a right-side `actions` slot. Pure layout — this repo does not call any platform API.
|
|
10
10
|
*
|
|
11
11
|
* Named `heading`, not `title` — matches dc-section-heading's own
|
|
12
12
|
* established convention for this kind of headline text, and avoids
|
|
@@ -42,8 +42,9 @@ export declare class DpToolbar extends LitElement {
|
|
|
42
42
|
static styles: import('lit').CSSResult;
|
|
43
43
|
heading: string;
|
|
44
44
|
subtitle: string;
|
|
45
|
-
/** Shows the sidebar drawer toggle. It is hidden at and above the desktop breakpoint. */
|
|
46
45
|
showToggle: boolean;
|
|
46
|
+
/** Whether the sidebar the toggle controls is shown in full — announced as the toggle's `aria-expanded`. */
|
|
47
|
+
expanded: boolean;
|
|
47
48
|
/** Accessible name of the sidebar toggle — supply one in the app's language. */
|
|
48
49
|
toggleLabel: string;
|
|
49
50
|
dragRegion: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './breakpoints.js';
|
|
2
2
|
export * from './components/page/dp-page.js';
|
|
3
|
+
export * from './components/list-detail/dp-list-detail.js';
|
|
3
4
|
export * from './components/sidebar/dp-sidebar.js';
|
|
4
5
|
export * from './components/toolbar/dp-toolbar.js';
|
|
5
6
|
export * from './components/shell/dp-shell.js';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { desktopMedia as e, desktopMinWidth as t } from "./breakpoints.js";
|
|
2
2
|
import { DpPage as n } from "./page.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
3
|
+
import { DpListDetail as r } from "./list-detail.js";
|
|
4
|
+
import { DpSidebar as i, DpSidebarActionEvent as a, DpSidebarActivateEvent as o, DpSidebarSelectEvent as s } from "./sidebar.js";
|
|
5
|
+
import { DpToolbar as c, DpToolbarToggleEvent as l } from "./toolbar.js";
|
|
6
|
+
import { DpShell as u, DpShellSidebarCloseEvent as d } from "./shell.js";
|
|
7
|
+
import { DpShortcutOverlay as f, DpShortcutOverlayDismissEvent as p } from "./shortcut-overlay.js";
|
|
8
|
+
export { r as DpListDetail, n as DpPage, u as DpShell, d as DpShellSidebarCloseEvent, f as DpShortcutOverlay, p as DpShortcutOverlayDismissEvent, i as DpSidebar, a as DpSidebarActionEvent, o as DpSidebarActivateEvent, s as DpSidebarSelectEvent, c as DpToolbar, l as DpToolbarToggleEvent, e as desktopMedia, t as desktopMinWidth };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { desktopMedia as e } from "./breakpoints.js";
|
|
2
|
+
import { t } from "./decorate-CafwLXg5.js";
|
|
3
|
+
import { LitElement as n, css as r, html as i } from "lit";
|
|
4
|
+
import { customElement as a, property as o } from "lit/decorators.js";
|
|
5
|
+
//#region src/components/list-detail/dp-list-detail.ts
|
|
6
|
+
var s = class extends n {
|
|
7
|
+
constructor(...e) {
|
|
8
|
+
super(...e), this.detailOpen = !1;
|
|
9
|
+
}
|
|
10
|
+
static {
|
|
11
|
+
this.styles = r`
|
|
12
|
+
:host {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex: 1;
|
|
15
|
+
min-height: 0;
|
|
16
|
+
height: 100%;
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
}
|
|
19
|
+
.list,
|
|
20
|
+
.detail {
|
|
21
|
+
min-width: 0;
|
|
22
|
+
min-height: 0;
|
|
23
|
+
overflow: auto;
|
|
24
|
+
box-sizing: border-box;
|
|
25
|
+
}
|
|
26
|
+
.list {
|
|
27
|
+
flex: 1;
|
|
28
|
+
}
|
|
29
|
+
.detail {
|
|
30
|
+
flex: 1;
|
|
31
|
+
display: none;
|
|
32
|
+
}
|
|
33
|
+
:host([detail-open]) .list {
|
|
34
|
+
display: none;
|
|
35
|
+
}
|
|
36
|
+
:host([detail-open]) .detail {
|
|
37
|
+
display: block;
|
|
38
|
+
}
|
|
39
|
+
@media ${e} {
|
|
40
|
+
:host([detail-open]) .list,
|
|
41
|
+
.list {
|
|
42
|
+
display: block;
|
|
43
|
+
flex: 0 0 var(--dp-list-detail-list-width, var(--dp-sidebar-width, 220px));
|
|
44
|
+
border-inline-end: 1px solid var(--dc-color-border, #e2e2e4);
|
|
45
|
+
}
|
|
46
|
+
.detail {
|
|
47
|
+
display: block;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
render() {
|
|
53
|
+
return i`
|
|
54
|
+
<div class="list" part="list"><slot name="list"></slot></div>
|
|
55
|
+
<div class="detail" part="detail"><slot></slot></div>
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
t([o({
|
|
60
|
+
type: Boolean,
|
|
61
|
+
reflect: !0,
|
|
62
|
+
attribute: "detail-open"
|
|
63
|
+
})], s.prototype, "detailOpen", void 0), s = t([a("dp-list-detail")], s);
|
|
64
|
+
//#endregion
|
|
65
|
+
export { s as DpListDetail };
|
package/dist/shell.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { desktopMedia as e } from "./breakpoints.js";
|
|
2
2
|
import { t } from "./decorate-CafwLXg5.js";
|
|
3
3
|
import { LitElement as n, css as r, html as i, nothing as a } from "lit";
|
|
4
4
|
import { customElement as o, property as s } from "lit/decorators.js";
|
package/dist/shortcut-overlay.js
CHANGED
|
@@ -11,8 +11,8 @@ var c = class extends Event {
|
|
|
11
11
|
}
|
|
12
12
|
}, l = 0, u = class extends t {
|
|
13
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.#
|
|
15
|
-
e.key === "Escape" && (e.preventDefault(), this.#
|
|
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.#t = (e) => {
|
|
15
|
+
e.key === "Escape" ? (e.preventDefault(), this.#r()) : e.key === "Tab" && (e.preventDefault(), this.#n()?.focus());
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
static {
|
|
@@ -104,18 +104,22 @@ var c = class extends Event {
|
|
|
104
104
|
`;
|
|
105
105
|
}
|
|
106
106
|
#e;
|
|
107
|
+
#t;
|
|
108
|
+
#n() {
|
|
109
|
+
return this.renderRoot.querySelector(".close");
|
|
110
|
+
}
|
|
107
111
|
updated(e) {
|
|
108
|
-
e.has("open") && (this.open ? window.addEventListener("keydown", this.#e) : window.removeEventListener("keydown", this.#e));
|
|
112
|
+
e.has("open") && (this.open ? (window.addEventListener("keydown", this.#t), this.#e = d(), this.#n()?.focus()) : (window.removeEventListener("keydown", this.#t), e.get("open") === !0 && this.#e?.focus(), this.#e = void 0));
|
|
109
113
|
}
|
|
110
114
|
disconnectedCallback() {
|
|
111
|
-
super.disconnectedCallback(), window.removeEventListener("keydown", this.#
|
|
115
|
+
super.disconnectedCallback(), window.removeEventListener("keydown", this.#t);
|
|
112
116
|
}
|
|
113
|
-
#
|
|
117
|
+
#r() {
|
|
114
118
|
this.dispatchEvent(new c());
|
|
115
119
|
}
|
|
116
120
|
render() {
|
|
117
121
|
return this.open ? r`
|
|
118
|
-
<div class="backdrop" @click=${() => this.#
|
|
122
|
+
<div class="backdrop" @click=${() => this.#r()}>
|
|
119
123
|
<div
|
|
120
124
|
class="panel"
|
|
121
125
|
role="dialog"
|
|
@@ -125,7 +129,7 @@ var c = class extends Event {
|
|
|
125
129
|
>
|
|
126
130
|
<div class="header">
|
|
127
131
|
<h2 id=${this.headingId}>${this.heading}</h2>
|
|
128
|
-
<button class="close" aria-label=${this.closeLabel} @click=${() => this.#
|
|
132
|
+
<button class="close" aria-label=${this.closeLabel} @click=${() => this.#r()}>×</button>
|
|
129
133
|
</div>
|
|
130
134
|
<div class="body">
|
|
131
135
|
${this.shortcuts.length === 0 ? r`<p class="empty">${this.emptyMessage}</p>` : r`
|
|
@@ -148,5 +152,10 @@ e([o({ type: Array })], u.prototype, "shortcuts", void 0), e([o({
|
|
|
148
152
|
type: Boolean,
|
|
149
153
|
reflect: !0
|
|
150
154
|
})], 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);
|
|
155
|
+
function d() {
|
|
156
|
+
let e = document.activeElement;
|
|
157
|
+
for (; e?.shadowRoot?.activeElement;) e = e.shadowRoot.activeElement;
|
|
158
|
+
return e instanceof HTMLElement && e !== document.body ? e : void 0;
|
|
159
|
+
}
|
|
151
160
|
//#endregion
|
|
152
161
|
export { u as DpShortcutOverlay, c as DpShortcutOverlayDismissEvent };
|
package/dist/sidebar.js
CHANGED
|
@@ -11,13 +11,20 @@ var c = (e) => Array.isArray(e.items), l = class extends Event {
|
|
|
11
11
|
}), this.itemId = e;
|
|
12
12
|
}
|
|
13
13
|
}, u = class extends Event {
|
|
14
|
+
constructor(e) {
|
|
15
|
+
super("dp-sidebar-activate", {
|
|
16
|
+
bubbles: !0,
|
|
17
|
+
composed: !0
|
|
18
|
+
}), this.itemId = e;
|
|
19
|
+
}
|
|
20
|
+
}, d = class extends Event {
|
|
14
21
|
constructor(e) {
|
|
15
22
|
super("dp-sidebar-action", {
|
|
16
23
|
bubbles: !0,
|
|
17
24
|
composed: !0
|
|
18
25
|
}), this.itemId = e;
|
|
19
26
|
}
|
|
20
|
-
},
|
|
27
|
+
}, f = class extends t {
|
|
21
28
|
constructor(...e) {
|
|
22
29
|
super(...e), this.items = [], this.bottomItems = [], this.activeId = "", this.header = "", this.navLabel = "", this.collapsed = !1, this.toggledGroups = /* @__PURE__ */ new Set();
|
|
23
30
|
}
|
|
@@ -194,7 +201,7 @@ var c = (e) => Array.isArray(e.items), l = class extends Event {
|
|
|
194
201
|
<button
|
|
195
202
|
class="item"
|
|
196
203
|
title=${this.collapsed ? e.label : i}
|
|
197
|
-
@click=${() => this.dispatchEvent(new
|
|
204
|
+
@click=${() => this.dispatchEvent(new d(e.id))}
|
|
198
205
|
>
|
|
199
206
|
${this.#r(e.id, e.icon)} ${this.collapsed ? i : r`<span class="label">${e.label}</span>`}
|
|
200
207
|
</button>
|
|
@@ -204,12 +211,15 @@ var c = (e) => Array.isArray(e.items), l = class extends Event {
|
|
|
204
211
|
return r`<span class="icon" aria-hidden="true"><slot name=${`icon-${e}`}>${t}</slot></span>`;
|
|
205
212
|
}
|
|
206
213
|
#i(e, t) {
|
|
207
|
-
if (!(t.href !== void 0 && (e.button !== 0 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey))
|
|
208
|
-
if (
|
|
209
|
-
|
|
210
|
-
|
|
214
|
+
if (!(t.href !== void 0 && (e.button !== 0 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey))) {
|
|
215
|
+
if (t.id !== this.activeId) {
|
|
216
|
+
if (!this.dispatchEvent(new l(t.id))) {
|
|
217
|
+
e.preventDefault();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
this.activeId = t.id;
|
|
211
221
|
}
|
|
212
|
-
this.
|
|
222
|
+
this.dispatchEvent(new u(t.id));
|
|
213
223
|
}
|
|
214
224
|
}
|
|
215
225
|
#a(e) {
|
|
@@ -217,12 +227,12 @@ var c = (e) => Array.isArray(e.items), l = class extends Event {
|
|
|
217
227
|
t.delete(e) || t.add(e), this.toggledGroups = t;
|
|
218
228
|
}
|
|
219
229
|
};
|
|
220
|
-
e([o({ type: Array })],
|
|
230
|
+
e([o({ type: Array })], f.prototype, "items", void 0), e([o({
|
|
221
231
|
type: Array,
|
|
222
232
|
attribute: "bottom-items"
|
|
223
|
-
})],
|
|
233
|
+
})], f.prototype, "bottomItems", void 0), e([o({ attribute: "active-id" })], f.prototype, "activeId", void 0), e([o()], f.prototype, "header", void 0), e([o({ attribute: "nav-label" })], f.prototype, "navLabel", void 0), e([o({
|
|
224
234
|
type: Boolean,
|
|
225
235
|
reflect: !0
|
|
226
|
-
})],
|
|
236
|
+
})], f.prototype, "collapsed", void 0), e([s()], f.prototype, "toggledGroups", void 0), f = e([a("dp-sidebar")], f);
|
|
227
237
|
//#endregion
|
|
228
|
-
export {
|
|
238
|
+
export { f as DpSidebar, d as DpSidebarActionEvent, u as DpSidebarActivateEvent, l as DpSidebarSelectEvent };
|
package/dist/toolbar.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
import { t as e } from "./
|
|
2
|
-
import { t } from "
|
|
3
|
-
import {
|
|
4
|
-
import { customElement as o, property as s } from "lit/decorators.js";
|
|
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";
|
|
5
4
|
//#region src/components/toolbar/dp-toolbar.ts
|
|
6
|
-
var
|
|
5
|
+
var s = class extends Event {
|
|
7
6
|
constructor() {
|
|
8
7
|
super("dp-toolbar-toggle", {
|
|
9
8
|
bubbles: !0,
|
|
10
9
|
composed: !0
|
|
11
10
|
});
|
|
12
11
|
}
|
|
13
|
-
},
|
|
12
|
+
}, c = class extends t {
|
|
14
13
|
constructor(...e) {
|
|
15
|
-
super(...e), this.heading = "", this.subtitle = "", this.showToggle = !1, this.toggleLabel = "Toggle sidebar", this.dragRegion = !1;
|
|
14
|
+
super(...e), this.heading = "", this.subtitle = "", this.showToggle = !1, this.expanded = !1, this.toggleLabel = "Toggle sidebar", this.dragRegion = !1;
|
|
16
15
|
}
|
|
17
16
|
static {
|
|
18
|
-
this.styles =
|
|
17
|
+
this.styles = n`
|
|
19
18
|
:host {
|
|
20
19
|
display: flex;
|
|
21
20
|
align-items: center;
|
|
@@ -60,13 +59,6 @@ var c = class extends Event {
|
|
|
60
59
|
outline: 2px solid var(--dc-color-accent, #2563eb);
|
|
61
60
|
outline-offset: 2px;
|
|
62
61
|
}
|
|
63
|
-
/* At desktop width dp-shell's sidebar is always beside the content: a drawer toggle there
|
|
64
|
-
would do nothing. */
|
|
65
|
-
@media ${e} {
|
|
66
|
-
.toggle {
|
|
67
|
-
display: none;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
62
|
.drag-handle {
|
|
71
63
|
flex: 1;
|
|
72
64
|
align-self: stretch;
|
|
@@ -83,15 +75,16 @@ var c = class extends Event {
|
|
|
83
75
|
super.connectedCallback(), this.setAttribute("role", "banner");
|
|
84
76
|
}
|
|
85
77
|
render() {
|
|
86
|
-
return
|
|
78
|
+
return r`
|
|
87
79
|
<div class="start">
|
|
88
|
-
${this.showToggle ?
|
|
80
|
+
${this.showToggle ? r`<button
|
|
89
81
|
class="toggle"
|
|
90
82
|
aria-label=${this.toggleLabel}
|
|
91
|
-
|
|
83
|
+
aria-expanded=${this.expanded ? "true" : "false"}
|
|
84
|
+
@click=${() => this.dispatchEvent(new s())}
|
|
92
85
|
>
|
|
93
86
|
☰
|
|
94
|
-
</button>` :
|
|
87
|
+
</button>` : i}
|
|
95
88
|
<span class="title">${this.subtitle || this.heading}</span>
|
|
96
89
|
</div>
|
|
97
90
|
<div class="drag-handle" part="drag-handle"></div>
|
|
@@ -99,13 +92,13 @@ var c = class extends Event {
|
|
|
99
92
|
`;
|
|
100
93
|
}
|
|
101
94
|
};
|
|
102
|
-
|
|
95
|
+
e([o()], c.prototype, "heading", void 0), e([o()], c.prototype, "subtitle", void 0), e([o({
|
|
103
96
|
type: Boolean,
|
|
104
97
|
attribute: "show-toggle"
|
|
105
|
-
})],
|
|
98
|
+
})], c.prototype, "showToggle", void 0), e([o({ type: Boolean })], c.prototype, "expanded", void 0), e([o({ attribute: "toggle-label" })], c.prototype, "toggleLabel", void 0), e([o({
|
|
106
99
|
type: Boolean,
|
|
107
100
|
reflect: !0,
|
|
108
101
|
attribute: "drag-region"
|
|
109
|
-
})],
|
|
102
|
+
})], c.prototype, "dragRegion", void 0), c = e([a("dp-toolbar")], c);
|
|
110
103
|
//#endregion
|
|
111
|
-
export {
|
|
104
|
+
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.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,11 +25,21 @@
|
|
|
25
25
|
"import": "./dist/index.js",
|
|
26
26
|
"default": "./dist/index.js"
|
|
27
27
|
},
|
|
28
|
+
"./breakpoints": {
|
|
29
|
+
"types": "./dist/breakpoints.d.ts",
|
|
30
|
+
"import": "./dist/breakpoints.js",
|
|
31
|
+
"default": "./dist/breakpoints.js"
|
|
32
|
+
},
|
|
28
33
|
"./page": {
|
|
29
34
|
"types": "./dist/components/page/dp-page.d.ts",
|
|
30
35
|
"import": "./dist/page.js",
|
|
31
36
|
"default": "./dist/page.js"
|
|
32
37
|
},
|
|
38
|
+
"./list-detail": {
|
|
39
|
+
"types": "./dist/components/list-detail/dp-list-detail.d.ts",
|
|
40
|
+
"import": "./dist/list-detail.js",
|
|
41
|
+
"default": "./dist/list-detail.js"
|
|
42
|
+
},
|
|
33
43
|
"./sidebar": {
|
|
34
44
|
"types": "./dist/components/sidebar/dp-sidebar.d.ts",
|
|
35
45
|
"import": "./dist/sidebar.js",
|
|
@@ -77,6 +87,7 @@
|
|
|
77
87
|
"@types/mocha": "^10.0.10",
|
|
78
88
|
"@web/dev-server-esbuild": "^2.0.0",
|
|
79
89
|
"@web/test-runner": "^1.0.0",
|
|
90
|
+
"@web/test-runner-commands": "^1.0.1",
|
|
80
91
|
"axe-core": "^4.13.0",
|
|
81
92
|
"storybook": "^10.6.0",
|
|
82
93
|
"typescript": "^6.0.3",
|
package/tokens.css
CHANGED