@excom/dismiss-watcher 0.1.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/.rush/temp/chunked-rush-logs/dismiss-watcher.apply-exports.chunks.jsonl +1 -0
- package/.rush/temp/chunked-rush-logs/dismiss-watcher.build_docs.chunks.jsonl +1 -0
- package/.rush/temp/chunked-rush-logs/dismiss-watcher.build_package-metas.chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/all.log +1 -0
- package/.rush/temp/operation/apply-exports/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/apply-exports/state.json +3 -0
- package/.rush/temp/operation/build_docs/all.log +1 -0
- package/.rush/temp/operation/build_docs/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/build_docs/state.json +3 -0
- package/.rush/temp/operation/build_package-metas/all.log +1 -0
- package/.rush/temp/operation/build_package-metas/log-chunks.jsonl +1 -0
- package/.rush/temp/operation/build_package-metas/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +3 -0
- package/config/rig.json +6 -0
- package/dismiss-watcher.ts +209 -0
- package/index.ts +21 -0
- package/package.json +48 -0
- package/rush-logs/dismiss-watcher.apply-exports.cache.log +1 -0
- package/rush-logs/dismiss-watcher.apply-exports.log +1 -0
- package/rush-logs/dismiss-watcher.build_docs.cache.log +1 -0
- package/rush-logs/dismiss-watcher.build_docs.log +1 -0
- package/rush-logs/dismiss-watcher.build_package-metas.cache.log +1 -0
- package/rush-logs/dismiss-watcher.build_package-metas.log +1 -0
- package/support/custom-elements.json +180 -0
- package/support/demos/drawer.html +19 -0
- package/support/demos/simple.html +24 -0
- package/support/dist-docs/dismiss-watcher.md +176 -0
- package/support/docs/README.md +62 -0
- package/support/package-meta.json +106 -0
- package/support/tests/dismiss-watcher.test.ts +370 -0
- package/support/tests/drawer.view.test.ts +71 -0
- package/support/tests/simple.view.test.ts +57 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: cd \"$RUSH_PROJECT_FOLDER\" && node ../heft-rig/scripts/apply-exports.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: cd "$RUSH_PROJECT_FOLDER" && node ../heft-rig/scripts/apply-exports.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: cd \"$RUSH_PROJECT_FOLDER\" && node ../heft-rig/scripts/apply-exports.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs \n"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"O","text":"Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs \n"}
|
package/config/rig.json
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { CloseWatcher } from "@excom/kit-shims";
|
|
2
|
+
import { selectOne } from "@excom/kit-utils";
|
|
3
|
+
import {
|
|
4
|
+
ConstructorType,
|
|
5
|
+
Neutron,
|
|
6
|
+
TEvent,
|
|
7
|
+
TokenList,
|
|
8
|
+
} from "@excom/neutron";
|
|
9
|
+
|
|
10
|
+
export type DismissWatcherReason = "escape" | "outside-click";
|
|
11
|
+
|
|
12
|
+
export type DismissWatcherDismissEvent = TEvent & {
|
|
13
|
+
type: "dismiss-watcher-dismiss";
|
|
14
|
+
detail: { reason: DismissWatcherReason };
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const DISMISS_EVENT = "dismiss-watcher-dismiss";
|
|
18
|
+
const OUTSIDE_EVENT = "mouseup";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Dismissal-request Adapter for drawers, menus, dialogs and popovers. While
|
|
22
|
+
* `is-active` it watches for Escape / the platform back gesture (through a
|
|
23
|
+
* `CloseWatcher`) and for a `mouseup` outside its target, then fires
|
|
24
|
+
* `dismiss-watcher-dismiss`. The default action invokes each `command-name`
|
|
25
|
+
* (`--close`) and dispatches each `fire-event` name at the target;
|
|
26
|
+
* `preventDefault()` keeps the panel open. Renders nothing — drop it inside
|
|
27
|
+
* the element being dismissed, or point `target-ref` at it.
|
|
28
|
+
*
|
|
29
|
+
* @summary Escape / back-gesture and outside-click dismissal for any panel.
|
|
30
|
+
*
|
|
31
|
+
* @fires dismiss-watcher-dismiss - A dismissal was requested; `detail.reason`
|
|
32
|
+
* is `"escape"` or `"outside-click"`. Default action: invoke each
|
|
33
|
+
* `command-name` on the target and dispatch each `fire-event` name at it
|
|
34
|
+
* as a bubbling `CustomEvent`. `preventDefault()` skips both.
|
|
35
|
+
* @type DismissWatcherDismissEvent
|
|
36
|
+
*/
|
|
37
|
+
export const DismissWatcher = Neutron({
|
|
38
|
+
tag: "dismiss-watcher",
|
|
39
|
+
props: {
|
|
40
|
+
/**
|
|
41
|
+
* @option
|
|
42
|
+
* @state
|
|
43
|
+
* Watchers are live while set. Gate it from Quark on the panel's open
|
|
44
|
+
* state, and write the inverse rule.
|
|
45
|
+
*/
|
|
46
|
+
isActive: Boolean,
|
|
47
|
+
/**
|
|
48
|
+
* @option
|
|
49
|
+
* Watch Escape / the back gesture through a `CloseWatcher`. When neither
|
|
50
|
+
* `watch-*` attribute is present both watchers are on.
|
|
51
|
+
*/
|
|
52
|
+
watchEscape: Boolean,
|
|
53
|
+
/**
|
|
54
|
+
* @option
|
|
55
|
+
* Watch for a `mouseup` on the document outside the target. When neither
|
|
56
|
+
* `watch-*` attribute is present both watchers are on.
|
|
57
|
+
*/
|
|
58
|
+
watchOutsideClick: Boolean,
|
|
59
|
+
/**
|
|
60
|
+
* @option
|
|
61
|
+
* Selector for the element being dismissed, `:scope`-relative
|
|
62
|
+
* (`:scope ~ nav`). Unset = the parent element.
|
|
63
|
+
*/
|
|
64
|
+
targetRef: String,
|
|
65
|
+
/**
|
|
66
|
+
* @option
|
|
67
|
+
* Commands invoked on the target as the default action of
|
|
68
|
+
* `dismiss-watcher-dismiss` — `--close` for a `<content-drawer>`, or any
|
|
69
|
+
* `--verb` the panel handles.
|
|
70
|
+
* @values <command>…
|
|
71
|
+
*/
|
|
72
|
+
commandName: TokenList,
|
|
73
|
+
/**
|
|
74
|
+
* @option
|
|
75
|
+
* Event names dispatched at the target (bubbling `CustomEvent`s) as the
|
|
76
|
+
* default action of `dismiss-watcher-dismiss`, for panels driven by
|
|
77
|
+
* events rather than commands (`menu-close`).
|
|
78
|
+
*/
|
|
79
|
+
fireEvent: TokenList,
|
|
80
|
+
// private state
|
|
81
|
+
_closeWatcher: Object as unknown as ConstructorType<CloseWatcher>,
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
.defineMethods({
|
|
85
|
+
_handleOutsideMouseup: (element, e: MouseEvent) => {
|
|
86
|
+
const target = resolveTarget(element);
|
|
87
|
+
if (!target || !(e.target instanceof Node) || target.contains(e.target)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
emit: [DISMISS_EVENT, { detail: { reason: "outside-click" } }],
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
_handleClose: () => [
|
|
95
|
+
/* CloseWatcher deactivates after `close`: drop it and re-arm before
|
|
96
|
+
emitting, so a cancelled dismissal (`preventDefault()`) keeps Escape. */
|
|
97
|
+
{ _closeWatcher: null },
|
|
98
|
+
{ _apply: [] },
|
|
99
|
+
{ emit: [DISMISS_EVENT, { detail: { reason: "escape" } }] },
|
|
100
|
+
],
|
|
101
|
+
})
|
|
102
|
+
// Second `defineMethods` so the handlers above are typed on the element
|
|
103
|
+
.defineMethods({
|
|
104
|
+
_apply: ({
|
|
105
|
+
watchEscape,
|
|
106
|
+
watchOutsideClick,
|
|
107
|
+
_closeWatcher,
|
|
108
|
+
_handleClose,
|
|
109
|
+
_handleOutsideMouseup,
|
|
110
|
+
}) => {
|
|
111
|
+
// Neither `watch-*` set → both
|
|
112
|
+
const wantsEscape = !!watchEscape || !watchOutsideClick;
|
|
113
|
+
const wantsOutsideClick = !!watchOutsideClick || !watchEscape;
|
|
114
|
+
return [
|
|
115
|
+
wantsOutsideClick
|
|
116
|
+
? {
|
|
117
|
+
addListener: [
|
|
118
|
+
OUTSIDE_EVENT,
|
|
119
|
+
_handleOutsideMouseup,
|
|
120
|
+
{ target: document },
|
|
121
|
+
],
|
|
122
|
+
}
|
|
123
|
+
: {
|
|
124
|
+
removeListener: [
|
|
125
|
+
OUTSIDE_EVENT,
|
|
126
|
+
_handleOutsideMouseup,
|
|
127
|
+
{ target: document },
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
wantsEscape
|
|
131
|
+
? !_closeWatcher && {
|
|
132
|
+
_closeWatcher: createCloseWatcher(_handleClose),
|
|
133
|
+
}
|
|
134
|
+
: !!_closeWatcher && {
|
|
135
|
+
_closeWatcher: destroyCloseWatcher(_closeWatcher, _handleClose),
|
|
136
|
+
},
|
|
137
|
+
].filter(Boolean);
|
|
138
|
+
},
|
|
139
|
+
_teardown: ({ _closeWatcher, _handleClose, _handleOutsideMouseup }) =>
|
|
140
|
+
[
|
|
141
|
+
{
|
|
142
|
+
removeListener: [
|
|
143
|
+
OUTSIDE_EVENT,
|
|
144
|
+
_handleOutsideMouseup,
|
|
145
|
+
{ target: document },
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
!!_closeWatcher && {
|
|
149
|
+
_closeWatcher: destroyCloseWatcher(_closeWatcher, _handleClose),
|
|
150
|
+
},
|
|
151
|
+
].filter(Boolean),
|
|
152
|
+
})
|
|
153
|
+
.onPropSet("isActive", () => ({ _apply: [] }))
|
|
154
|
+
.onPropUnset("isActive", () => ({ _teardown: [] }))
|
|
155
|
+
.onPropChanged(
|
|
156
|
+
["watchEscape", "watchOutsideClick", "targetRef"],
|
|
157
|
+
({ isActive }) => !!isActive && { _apply: [] }
|
|
158
|
+
)
|
|
159
|
+
.onConnected(
|
|
160
|
+
({ wasMounted, isActive, isMoving }) =>
|
|
161
|
+
// Real reconnect rebuilds; first mount is the prop flush
|
|
162
|
+
wasMounted && !!isActive && !isMoving && { _apply: [] }
|
|
163
|
+
)
|
|
164
|
+
.onDisconnected(
|
|
165
|
+
({ isMoving }) =>
|
|
166
|
+
// Neutron restores tracked listeners on a move; keep the watcher too
|
|
167
|
+
!isMoving && { _teardown: [] }
|
|
168
|
+
)
|
|
169
|
+
.onEventDefault(DISMISS_EVENT, (element) => {
|
|
170
|
+
const target = resolveTarget(element);
|
|
171
|
+
const commands = element.commandName || [];
|
|
172
|
+
const names = element.fireEvent || [];
|
|
173
|
+
return (
|
|
174
|
+
!!target && [
|
|
175
|
+
commands.length > 0 && {
|
|
176
|
+
commands: commands.map((name) => [name, { target }]),
|
|
177
|
+
},
|
|
178
|
+
names.length > 0 && {
|
|
179
|
+
emits: names.map((type) => [type, { target }]),
|
|
180
|
+
},
|
|
181
|
+
]
|
|
182
|
+
);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
/** `target-ref`, `:scope`-relative to the watcher; default = parent. */
|
|
186
|
+
function resolveTarget(
|
|
187
|
+
element: HTMLElement & { targetRef?: string | null }
|
|
188
|
+
): HTMLElement | null {
|
|
189
|
+
return element.targetRef
|
|
190
|
+
? selectOne(element.targetRef, { scope: element })
|
|
191
|
+
: element.parentElement;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function createCloseWatcher(onClose: EventListener) {
|
|
195
|
+
const watcher = new CloseWatcher();
|
|
196
|
+
watcher.addEventListener("close", onClose);
|
|
197
|
+
return watcher;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function destroyCloseWatcher(
|
|
201
|
+
watcher: CloseWatcher | null | undefined,
|
|
202
|
+
onClose: EventListener
|
|
203
|
+
) {
|
|
204
|
+
if (watcher) {
|
|
205
|
+
watcher.removeEventListener("close", onClose);
|
|
206
|
+
watcher.destroy();
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
}
|
package/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { DismissWatcher } from "./dismiss-watcher";
|
|
2
|
+
|
|
3
|
+
DismissWatcher.define();
|
|
4
|
+
|
|
5
|
+
export { DismissWatcher };
|
|
6
|
+
export type {
|
|
7
|
+
DismissWatcherDismissEvent,
|
|
8
|
+
DismissWatcherReason,
|
|
9
|
+
} from "./dismiss-watcher";
|
|
10
|
+
|
|
11
|
+
type T_HTMLDismissWatcherElement = typeof DismissWatcher.CustomElement;
|
|
12
|
+
declare global {
|
|
13
|
+
interface HTMLDismissWatcherElement extends T_HTMLDismissWatcherElement {}
|
|
14
|
+
interface Window {
|
|
15
|
+
HTMLDismissWatcherElement: HTMLDismissWatcherElement;
|
|
16
|
+
}
|
|
17
|
+
interface HTMLElementTagNameMap {
|
|
18
|
+
"dismiss-watcher": HTMLDismissWatcherElement;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export type { HTMLDismissWatcherElement };
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@excom/dismiss-watcher",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "<dismiss-watcher> custom element",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=24.13.0"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@excom/kit-utils": "^0.1.0",
|
|
12
|
+
"@excom/neutron": "^0.1.0",
|
|
13
|
+
"@excom/kit-shims": "^0.1.0"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@excom/content-drawer": "^0.1.0",
|
|
18
|
+
"@excom/heft-rig": "^0.1.0",
|
|
19
|
+
"@excom/quark": "^0.1.0",
|
|
20
|
+
"@excom/event-handler": "^0.1.0",
|
|
21
|
+
"@excom/quark-sheet": "^0.1.0"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"url": "excom-dev/nucleus",
|
|
25
|
+
"directory": "packages/dismiss-watcher"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/excom-dev/nucleus/tree/main/packages/dismiss-watcher/support/docs/README.md",
|
|
28
|
+
"bugs": "https://github.com/excom-dev/nucleus/issues",
|
|
29
|
+
"keywords": [
|
|
30
|
+
"dismiss-watcher",
|
|
31
|
+
"neutron",
|
|
32
|
+
"custom-elements"
|
|
33
|
+
],
|
|
34
|
+
"excom": {
|
|
35
|
+
"packageType": "kit-element"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "node node_modules/@excom/heft-rig/scripts/vite-build.mjs",
|
|
39
|
+
"build:watch": "node node_modules/@excom/heft-rig/scripts/vite-build-watch.mjs",
|
|
40
|
+
"format": "node node_modules/@excom/heft-rig/scripts/format.mjs",
|
|
41
|
+
"test": "node node_modules/@excom/heft-rig/scripts/vitest.mjs",
|
|
42
|
+
"coverage": "node node_modules/@excom/heft-rig/scripts/coverage.mjs",
|
|
43
|
+
"dev": "node node_modules/@excom/heft-rig/scripts/vite-dev.mjs",
|
|
44
|
+
"preview": "node node_modules/@excom/heft-rig/scripts/vite-preview.mjs",
|
|
45
|
+
"build:package-metas": "node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs",
|
|
46
|
+
"build:docs": "node node_modules/@excom/heft-rig/scripts/build-docs.mjs"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Caching has been disabled for this project's "apply-exports" command.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: cd "$RUSH_PROJECT_FOLDER" && node ../heft-rig/scripts/apply-exports.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This project does not define the caching behavior of the "build:docs" command, so caching has been disabled.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-docs.mjs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This project does not define the caching behavior of the "build:package-metas" command, so caching has been disabled.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Invoking: node node_modules/@excom/heft-rig/scripts/build-package-metas.mjs
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"modules": [
|
|
4
|
+
{
|
|
5
|
+
"kind": "javascript-module",
|
|
6
|
+
"path": "dismiss-watcher.ts",
|
|
7
|
+
"declarations": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "class",
|
|
10
|
+
"name": "DismissWatcher",
|
|
11
|
+
"customElement": true,
|
|
12
|
+
"tagName": "dismiss-watcher",
|
|
13
|
+
"summary": "Escape / back-gesture and outside-click dismissal for any panel.",
|
|
14
|
+
"description": "Dismissal-request Adapter for drawers, menus, dialogs and popovers. While `is-active` it watches for Escape / the platform back gesture (through a `CloseWatcher`) and for a `mouseup` outside its target, then fires `dismiss-watcher-dismiss`. The default action invokes each `command-name` (`--close`) and dispatches each `fire-event` name at the target; `preventDefault()` keeps the panel open. Renders nothing — drop it inside the element being dismissed, or point `target-ref` at it.",
|
|
15
|
+
"attributes": [
|
|
16
|
+
{
|
|
17
|
+
"name": "is-active",
|
|
18
|
+
"type": {
|
|
19
|
+
"text": "boolean"
|
|
20
|
+
},
|
|
21
|
+
"description": "Watchers are live while set. Gate it from Quark on the panel's open state, and write the inverse rule.",
|
|
22
|
+
"fieldName": "isActive"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "watch-escape",
|
|
26
|
+
"type": {
|
|
27
|
+
"text": "boolean"
|
|
28
|
+
},
|
|
29
|
+
"description": "Watch Escape / the back gesture through a `CloseWatcher`. When neither `watch-*` attribute is present both watchers are on.",
|
|
30
|
+
"fieldName": "watchEscape"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "watch-outside-click",
|
|
34
|
+
"type": {
|
|
35
|
+
"text": "boolean"
|
|
36
|
+
},
|
|
37
|
+
"description": "Watch for a `mouseup` on the document outside the target. When neither `watch-*` attribute is present both watchers are on.",
|
|
38
|
+
"fieldName": "watchOutsideClick"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "target-ref",
|
|
42
|
+
"type": {
|
|
43
|
+
"text": "string"
|
|
44
|
+
},
|
|
45
|
+
"description": "Selector for the element being dismissed, `:scope`-relative (`:scope ~ nav`). Unset = the parent element.",
|
|
46
|
+
"fieldName": "targetRef"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "command-name",
|
|
50
|
+
"type": {
|
|
51
|
+
"text": "tokenlist"
|
|
52
|
+
},
|
|
53
|
+
"description": "Commands invoked on the target as the default action of `dismiss-watcher-dismiss` — `--close` for a `<content-drawer>`, or any `--verb` the panel handles.",
|
|
54
|
+
"fieldName": "commandName",
|
|
55
|
+
"values": [
|
|
56
|
+
"<command>…"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "fire-event",
|
|
61
|
+
"type": {
|
|
62
|
+
"text": "tokenlist"
|
|
63
|
+
},
|
|
64
|
+
"description": "Event names dispatched at the target (bubbling `CustomEvent`s) as the default action of `dismiss-watcher-dismiss`, for panels driven by events rather than commands (`menu-close`).",
|
|
65
|
+
"fieldName": "fireEvent"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"members": [
|
|
69
|
+
{
|
|
70
|
+
"kind": "field",
|
|
71
|
+
"name": "isActive",
|
|
72
|
+
"type": {
|
|
73
|
+
"text": "boolean"
|
|
74
|
+
},
|
|
75
|
+
"privacy": "public",
|
|
76
|
+
"readonly": false,
|
|
77
|
+
"description": "Watchers are live while set. Gate it from Quark on the panel's open state, and write the inverse rule.",
|
|
78
|
+
"_neutron": {
|
|
79
|
+
"surface": "hybrid"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"kind": "field",
|
|
84
|
+
"name": "watchEscape",
|
|
85
|
+
"type": {
|
|
86
|
+
"text": "boolean"
|
|
87
|
+
},
|
|
88
|
+
"privacy": "public",
|
|
89
|
+
"readonly": false,
|
|
90
|
+
"description": "Watch Escape / the back gesture through a `CloseWatcher`. When neither `watch-*` attribute is present both watchers are on.",
|
|
91
|
+
"_neutron": {
|
|
92
|
+
"surface": "option"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"kind": "field",
|
|
97
|
+
"name": "watchOutsideClick",
|
|
98
|
+
"type": {
|
|
99
|
+
"text": "boolean"
|
|
100
|
+
},
|
|
101
|
+
"privacy": "public",
|
|
102
|
+
"readonly": false,
|
|
103
|
+
"description": "Watch for a `mouseup` on the document outside the target. When neither `watch-*` attribute is present both watchers are on.",
|
|
104
|
+
"_neutron": {
|
|
105
|
+
"surface": "option"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"kind": "field",
|
|
110
|
+
"name": "targetRef",
|
|
111
|
+
"type": {
|
|
112
|
+
"text": "string"
|
|
113
|
+
},
|
|
114
|
+
"privacy": "public",
|
|
115
|
+
"readonly": false,
|
|
116
|
+
"description": "Selector for the element being dismissed, `:scope`-relative (`:scope ~ nav`). Unset = the parent element.",
|
|
117
|
+
"_neutron": {
|
|
118
|
+
"surface": "option"
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"kind": "field",
|
|
123
|
+
"name": "commandName",
|
|
124
|
+
"type": {
|
|
125
|
+
"text": "tokenlist"
|
|
126
|
+
},
|
|
127
|
+
"privacy": "public",
|
|
128
|
+
"readonly": false,
|
|
129
|
+
"description": "Commands invoked on the target as the default action of `dismiss-watcher-dismiss` — `--close` for a `<content-drawer>`, or any `--verb` the panel handles.",
|
|
130
|
+
"_neutron": {
|
|
131
|
+
"surface": "option"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"kind": "field",
|
|
136
|
+
"name": "fireEvent",
|
|
137
|
+
"type": {
|
|
138
|
+
"text": "tokenlist"
|
|
139
|
+
},
|
|
140
|
+
"privacy": "public",
|
|
141
|
+
"readonly": false,
|
|
142
|
+
"description": "Event names dispatched at the target (bubbling `CustomEvent`s) as the default action of `dismiss-watcher-dismiss`, for panels driven by events rather than commands (`menu-close`).",
|
|
143
|
+
"_neutron": {
|
|
144
|
+
"surface": "option"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
"events": [
|
|
149
|
+
{
|
|
150
|
+
"name": "dismiss-watcher-dismiss",
|
|
151
|
+
"description": "A dismissal was requested; `detail.reason` is `\"escape\"` or `\"outside-click\"`. Default action: invoke each `command-name` on the target and dispatch each `fire-event` name at it as a bubbling `CustomEvent`. `preventDefault()` skips both.",
|
|
152
|
+
"type": {
|
|
153
|
+
"text": "DismissWatcherDismissEvent",
|
|
154
|
+
"expanded": "CustomEvent & { type: \"dismiss-watcher-dismiss\"; detail: { reason: \"escape\" | \"outside-click\" }; bubbles: true; cancelable: true; composed: true }"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
"exports": [
|
|
161
|
+
{
|
|
162
|
+
"kind": "js",
|
|
163
|
+
"name": "DismissWatcher",
|
|
164
|
+
"declaration": {
|
|
165
|
+
"name": "DismissWatcher",
|
|
166
|
+
"module": "dismiss-watcher.ts"
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"kind": "custom-element-definition",
|
|
171
|
+
"name": "dismiss-watcher",
|
|
172
|
+
"declaration": {
|
|
173
|
+
"name": "DismissWatcher",
|
|
174
|
+
"module": "dismiss-watcher.ts"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<section>
|
|
2
|
+
<quark-sheet>
|
|
3
|
+
:scope {
|
|
4
|
+
content-drawer[is-open] dismiss-watcher { is-active: ""; }
|
|
5
|
+
content-drawer:not([is-open]) dismiss-watcher { is-active: none; }
|
|
6
|
+
}
|
|
7
|
+
</quark-sheet>
|
|
8
|
+
<button type="button" command="--open" commandfor="demo-dismiss-drawer">
|
|
9
|
+
Open drawer
|
|
10
|
+
</button>
|
|
11
|
+
<content-drawer id="demo-dismiss-drawer">
|
|
12
|
+
<dismiss-watcher watch-escape watch-outside-click command-name="--close"></dismiss-watcher>
|
|
13
|
+
<header>
|
|
14
|
+
<h2>Drawer</h2>
|
|
15
|
+
</header>
|
|
16
|
+
<p>Press Escape or click outside to close.</p>
|
|
17
|
+
</content-drawer>
|
|
18
|
+
<event-handler class="tag-backdrop" role="presentation" target-ref="content-drawer:has(+ :scope)" command-name="--close"></event-handler>
|
|
19
|
+
</section>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<div>
|
|
2
|
+
<quark-sheet>
|
|
3
|
+
:scope {
|
|
4
|
+
@on menu-open { data-is-open: ""; }
|
|
5
|
+
@on dismiss-watcher-dismiss { data-is-open: none; }
|
|
6
|
+
&[data-is-open] dismiss-watcher { is-active: ""; }
|
|
7
|
+
&:not([data-is-open]) dismiss-watcher { is-active: none; }
|
|
8
|
+
}
|
|
9
|
+
</quark-sheet>
|
|
10
|
+
<style>
|
|
11
|
+
[data-demo-menu] { display: none; }
|
|
12
|
+
[data-is-open] > [data-demo-menu] { display: block; }
|
|
13
|
+
</style>
|
|
14
|
+
<event-handler role="button" fire-event="menu-open">Open menu</event-handler>
|
|
15
|
+
<nav data-demo-menu>
|
|
16
|
+
<dismiss-watcher></dismiss-watcher>
|
|
17
|
+
<ul>
|
|
18
|
+
<li><a href="#">Profile</a></li>
|
|
19
|
+
<li><a href="#">Settings</a></li>
|
|
20
|
+
<li><a href="#">Sign out</a></li>
|
|
21
|
+
</ul>
|
|
22
|
+
<p>Press Escape or click outside to close.</p>
|
|
23
|
+
</nav>
|
|
24
|
+
</div>
|