sinwan-ui-core 0.0.0 → 1.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.
@@ -0,0 +1,116 @@
1
+ import {
2
+ useAnchorPosition2
3
+ } from "./chunk-6r59k5mb.js";
4
+ import {
5
+ Presence2,
6
+ UiPortal2
7
+ } from "./chunk-ejwby1pn.js";
8
+
9
+ // src/menu-sub.tsx
10
+ import { unwrap as _$unwrap } from "sinwan/reactivity";
11
+ import { cc } from "sinwan/component";
12
+ import { onUnmounted } from "sinwan/component";
13
+ import {
14
+ computed,
15
+ effect,
16
+ signal,
17
+ untrack
18
+ } from "sinwan/reactivity";
19
+ import { jsx } from "sinwan/jsx-runtime";
20
+ function createMenuSubApi2(options) {
21
+ const openLocal = signal(options.defaultOpen ?? false);
22
+ const open = options.controlled ? computed(options.readOpen) : openLocal;
23
+ const set = (next) => {
24
+ if (!options.controlled)
25
+ openLocal.value = next;
26
+ };
27
+ const triggerEl = signal(null);
28
+ let closeTimer;
29
+ function cancelClose() {
30
+ if (closeTimer !== undefined) {
31
+ window.clearTimeout(closeTimer);
32
+ closeTimer = undefined;
33
+ }
34
+ }
35
+ function setOpen(value) {
36
+ cancelClose();
37
+ set(value);
38
+ options.onOpenChange?.(value);
39
+ }
40
+ function requestClose(delayMs = 100) {
41
+ cancelClose();
42
+ closeTimer = window.setTimeout(() => {
43
+ closeTimer = undefined;
44
+ setOpen(false);
45
+ }, delayMs);
46
+ }
47
+ const parentOpen = options.parentOpen;
48
+ if (parentOpen) {
49
+ effect(() => {
50
+ if (parentOpen())
51
+ return;
52
+ untrack(() => {
53
+ if (open.value)
54
+ setOpen(false);
55
+ });
56
+ });
57
+ }
58
+ onUnmounted(cancelClose);
59
+ return { open, setOpen, triggerEl, cancelClose, requestClose };
60
+ }
61
+ function createMenuSubTriggerHandlers2(api) {
62
+ function openSub() {
63
+ api.cancelClose();
64
+ if (!api.open.value)
65
+ api.setOpen(true);
66
+ }
67
+ return {
68
+ onMouseEnter: openSub,
69
+ onMouseLeave: () => api.requestClose(),
70
+ onClick: openSub,
71
+ onKeyDown: (event) => {
72
+ if (event.key !== "ArrowRight")
73
+ return;
74
+ event.preventDefault();
75
+ openSub();
76
+ }
77
+ };
78
+ }
79
+ function isInsideMenuSubContent2(target) {
80
+ return target instanceof Element && target.closest("[data-slot$='-sub-content']") != null;
81
+ }
82
+ var MenuSubContentLayer2 = cc(function MenuSubContentLayer(props) {
83
+ const contentEl = signal(null);
84
+ const { style, side } = useAnchorPosition2({
85
+ open: props.api.open,
86
+ trigger: props.api.triggerEl,
87
+ content: contentEl,
88
+ placement: "right",
89
+ align: "start",
90
+ gap: 4,
91
+ fallbackSize: { width: 128, height: 120 }
92
+ });
93
+ function subState() {
94
+ return props.api.open.value ? "open" : "closed";
95
+ }
96
+ return /* @__PURE__ */ jsx(Presence2, {
97
+ present: () => _$unwrap(props).api.open.value,
98
+ children: /* @__PURE__ */ jsx(UiPortal2, {
99
+ children: /* @__PURE__ */ jsx("div", {
100
+ "data-slot": () => _$unwrap(props).slot,
101
+ "data-state": subState,
102
+ "data-side": () => side.value,
103
+ class: () => _$unwrap(props).class,
104
+ style: () => style.value,
105
+ onmouseenter: () => props.api.cancelClose(),
106
+ onmouseleave: () => props.api.requestClose(),
107
+ ref: (el) => {
108
+ contentEl.value = el;
109
+ },
110
+ children: () => _$unwrap(props).children
111
+ })
112
+ })
113
+ });
114
+ });
115
+
116
+ export { createMenuSubApi2, createMenuSubTriggerHandlers2, isInsideMenuSubContent2, MenuSubContentLayer2 };
@@ -0,0 +1,511 @@
1
+ import {
2
+ Slot2
3
+ } from "./chunk-bw9vp0y9.js";
4
+ import {
5
+ useAnchorPosition2
6
+ } from "./chunk-6r59k5mb.js";
7
+ import {
8
+ Presence2,
9
+ UiPortal2,
10
+ trapFocus2
11
+ } from "./chunk-ejwby1pn.js";
12
+ import {
13
+ isDismissExemptPointerTarget2
14
+ } from "./chunk-9whagkb6.js";
15
+
16
+ // src/overlay.tsx
17
+ import { _$createTemplate } from "sinwan/renderer/web";
18
+ import { unwrap as _$unwrap } from "sinwan/reactivity";
19
+ import {
20
+ cc,
21
+ inject,
22
+ onMounted,
23
+ onUnmounted,
24
+ provide,
25
+ createLiveRest as _$createLiveRest,
26
+ getSpreadProps as _$getSpreadProps
27
+ } from "sinwan/component";
28
+ import { computed, signal } from "sinwan/reactivity";
29
+ import { jsx, Fragment } from "sinwan/jsx-runtime";
30
+ var _$tmpl_0 = {
31
+ html: '<button type="button" data-slot="dialog-trigger"></button>',
32
+ slots: [
33
+ { path: [], type: "attr", name: "class" },
34
+ { path: [], type: "event", name: "onclick" },
35
+ { path: [], type: "ref", name: "ref" },
36
+ { path: [], type: "child" }
37
+ ]
38
+ };
39
+ var _$tmpl_1 = {
40
+ html: '<button type="button" data-slot="dialog-close"></button>',
41
+ slots: [
42
+ { path: [], type: "attr", name: "class" },
43
+ { path: [], type: "event", name: "onclick" },
44
+ { path: [], type: "child" }
45
+ ]
46
+ };
47
+ var _$tmpl_2 = {
48
+ html: '<div data-slot="collapsible" data-state=""></div>',
49
+ slots: [
50
+ { path: [], type: "attr", name: "data-state" },
51
+ { path: [], type: "attr", name: "class" },
52
+ { path: [], type: "child" }
53
+ ]
54
+ };
55
+ var _$tmpl_3 = {
56
+ html: '<button type="button" data-slot="collapsible-trigger" aria-expanded=""></button>',
57
+ slots: [
58
+ { path: [], type: "attr", name: "class" },
59
+ { path: [], type: "attr", name: "aria-expanded" },
60
+ { path: [], type: "event", name: "onclick" },
61
+ { path: [], type: "child" }
62
+ ]
63
+ };
64
+ var _$tmpl_4 = {
65
+ html: '<button type="button" data-slot="popover-trigger" aria-expanded=""></button>',
66
+ slots: [
67
+ { path: [], type: "attr", name: "class" },
68
+ { path: [], type: "attr", name: "aria-expanded" },
69
+ { path: [], type: "event", name: "onclick" },
70
+ { path: [], type: "ref", name: "ref" },
71
+ { path: [], type: "child" }
72
+ ]
73
+ };
74
+ var REOPEN_LOCK_MS = 280;
75
+ function createOpenState(props) {
76
+ const openLocal = signal(props.defaultOpen ?? false);
77
+ const open = "open" in props ? computed(() => Boolean(props.open)) : openLocal;
78
+ const set = (next) => {
79
+ if (!("open" in props))
80
+ openLocal.value = next;
81
+ };
82
+ let closeTimer;
83
+ let pointerOverTrigger = false;
84
+ let hoverOpenBlocked = false;
85
+ let reopenLockUntil = 0;
86
+ function cancelClose() {
87
+ if (closeTimer !== undefined) {
88
+ window.clearTimeout(closeTimer);
89
+ closeTimer = undefined;
90
+ }
91
+ }
92
+ function setOpen(value) {
93
+ cancelClose();
94
+ if (value) {
95
+ if (Date.now() < reopenLockUntil)
96
+ return;
97
+ } else {
98
+ if (pointerOverTrigger)
99
+ hoverOpenBlocked = true;
100
+ reopenLockUntil = Date.now() + REOPEN_LOCK_MS;
101
+ }
102
+ set(value);
103
+ props.onOpenChange?.(value);
104
+ }
105
+ function requestClose(delayMs = 0) {
106
+ cancelClose();
107
+ closeTimer = window.setTimeout(() => {
108
+ closeTimer = undefined;
109
+ setOpen(false);
110
+ }, delayMs);
111
+ }
112
+ function isHoverOpenBlocked() {
113
+ return hoverOpenBlocked;
114
+ }
115
+ function setPointerOverTrigger(over) {
116
+ pointerOverTrigger = over;
117
+ if (!over)
118
+ hoverOpenBlocked = false;
119
+ }
120
+ onUnmounted(cancelClose);
121
+ return {
122
+ open,
123
+ setOpen,
124
+ triggerEl: signal(null),
125
+ requestClose,
126
+ cancelClose,
127
+ isHoverOpenBlocked,
128
+ setPointerOverTrigger
129
+ };
130
+ }
131
+ var DialogKey2 = Symbol("sinwan-ui.dialog");
132
+ var DialogRoot2 = cc((props) => {
133
+ const api = createOpenState(props);
134
+ provide(DialogKey2, api);
135
+ return /* @__PURE__ */ jsx(Fragment, {
136
+ children: () => _$unwrap(props).children
137
+ });
138
+ });
139
+ var DialogTrigger2 = cc((props) => {
140
+ const api = inject(DialogKey2);
141
+ const onClick = () => {
142
+ api.setOpen(true);
143
+ };
144
+ const ref = (el) => {
145
+ api.triggerEl.value = el;
146
+ };
147
+ if (props.asChild) {
148
+ return /* @__PURE__ */ jsx(Slot2, {
149
+ class: () => _$unwrap(props).class,
150
+ onclick: onClick,
151
+ ref,
152
+ children: () => _$unwrap(props).children
153
+ });
154
+ }
155
+ return _$createTemplate(_$tmpl_0, [
156
+ () => _$unwrap(props).class,
157
+ onClick,
158
+ ref,
159
+ () => _$unwrap(props).children
160
+ ]);
161
+ });
162
+ var DialogClose2 = cc((props) => {
163
+ const api = inject(DialogKey2);
164
+ const onClick = () => {
165
+ api.setOpen(false);
166
+ };
167
+ if (props.asChild) {
168
+ return /* @__PURE__ */ jsx(Slot2, {
169
+ class: () => _$unwrap(props).class,
170
+ onclick: onClick,
171
+ children: () => _$unwrap(props).children
172
+ });
173
+ }
174
+ return _$createTemplate(_$tmpl_1, [
175
+ () => _$unwrap(props).class,
176
+ onClick,
177
+ () => _$unwrap(props).children
178
+ ]);
179
+ });
180
+ var DialogOverlay2 = cc((props) => {
181
+ const api = inject(DialogKey2);
182
+ function dismiss() {
183
+ api.setOpen(false);
184
+ }
185
+ function overlayState() {
186
+ return api.open.value ? "open" : "closed";
187
+ }
188
+ return /* @__PURE__ */ jsx(Presence2, {
189
+ present: () => api.open.value,
190
+ children: /* @__PURE__ */ jsx(UiPortal2, {
191
+ children: /* @__PURE__ */ jsx("div", {
192
+ "data-slot": "dialog-overlay",
193
+ "data-state": overlayState,
194
+ class: () => _$unwrap(props).class,
195
+ onclick: dismiss
196
+ })
197
+ })
198
+ });
199
+ });
200
+ var DialogContent2 = cc((props) => {
201
+ const dataAttrs = _$createLiveRest(props, [
202
+ "children",
203
+ "class",
204
+ "onEscapeKeyDown",
205
+ "data-side",
206
+ "data-size",
207
+ "data-vaul-drawer-direction",
208
+ "data-slot"
209
+ ]);
210
+ const api = inject(DialogKey2);
211
+ let contentEl = null;
212
+ let previousFocus = null;
213
+ onMounted(() => {
214
+ function onKey(e) {
215
+ if (!api.open.value)
216
+ return;
217
+ if (e.key === "Escape") {
218
+ props.onEscapeKeyDown?.(e);
219
+ if (!e.defaultPrevented)
220
+ api.setOpen(false);
221
+ }
222
+ if (contentEl)
223
+ trapFocus2(e, contentEl);
224
+ }
225
+ function cleanup() {
226
+ document.removeEventListener("keydown", onKey);
227
+ }
228
+ document.addEventListener("keydown", onKey);
229
+ onUnmounted(cleanup);
230
+ });
231
+ function contentState() {
232
+ return api.open.value ? "open" : "closed";
233
+ }
234
+ return /* @__PURE__ */ jsx(Presence2, {
235
+ present: () => api.open.value,
236
+ children: /* @__PURE__ */ jsx(UiPortal2, {
237
+ children: /* @__PURE__ */ jsx("div", {
238
+ ..._$getSpreadProps(dataAttrs),
239
+ role: "dialog",
240
+ "aria-modal": "true",
241
+ "data-slot": () => props["data-slot"] === undefined ? "dialog-content" : props["data-slot"],
242
+ "data-state": contentState,
243
+ "data-side": () => props["data-side"],
244
+ "data-size": () => props["data-size"],
245
+ "data-vaul-drawer-direction": () => props["data-vaul-drawer-direction"],
246
+ class: () => _$unwrap(props).class,
247
+ ref: function contentRef(el) {
248
+ contentEl = el;
249
+ if (el) {
250
+ previousFocus = document.activeElement;
251
+ el.focus?.();
252
+ } else if (previousFocus) {
253
+ previousFocus.focus?.();
254
+ }
255
+ },
256
+ tabIndex: -1,
257
+ onclick: function stopBubble(e) {
258
+ e.stopPropagation();
259
+ },
260
+ children: () => _$unwrap(props).children
261
+ })
262
+ })
263
+ });
264
+ });
265
+ var CollapsibleKey2 = Symbol("sinwan-ui.collapsible");
266
+ var CollapsibleRoot2 = cc((props) => {
267
+ const openLocal = signal(props.defaultOpen ?? false);
268
+ const open = "open" in props ? computed(() => Boolean(props.open)) : openLocal;
269
+ const set = (next) => {
270
+ if (!("open" in props))
271
+ openLocal.value = next;
272
+ };
273
+ provide(CollapsibleKey2, {
274
+ open,
275
+ setOpen: function setOpen(v) {
276
+ set(v);
277
+ props.onOpenChange?.(v);
278
+ }
279
+ });
280
+ return _$createTemplate(_$tmpl_2, [
281
+ function stateAttr() {
282
+ return open.value ? "open" : "closed";
283
+ },
284
+ () => _$unwrap(props).class,
285
+ () => _$unwrap(props).children
286
+ ]);
287
+ });
288
+ var CollapsibleTrigger2 = cc((props) => {
289
+ const api = inject(CollapsibleKey2);
290
+ const toggle = () => {
291
+ api.setOpen(!api.open.value);
292
+ };
293
+ if (props.asChild) {
294
+ return /* @__PURE__ */ jsx(Slot2, {
295
+ class: () => _$unwrap(props).class,
296
+ onclick: toggle,
297
+ children: () => _$unwrap(props).children
298
+ });
299
+ }
300
+ return _$createTemplate(_$tmpl_3, [
301
+ () => _$unwrap(props).class,
302
+ function expanded() {
303
+ return api.open.value;
304
+ },
305
+ toggle,
306
+ () => _$unwrap(props).children
307
+ ]);
308
+ });
309
+ var CollapsibleContent2 = cc((props) => {
310
+ const api = inject(CollapsibleKey2);
311
+ function stateAttr() {
312
+ return api.open.value ? "open" : "closed";
313
+ }
314
+ function bindContent(el) {
315
+ if (el == null)
316
+ return;
317
+ const node = el;
318
+ function measure() {
319
+ const inner = node.firstElementChild;
320
+ const height = inner instanceof HTMLElement ? inner.scrollHeight : node.scrollHeight;
321
+ node.style.setProperty("--radix-collapsible-content-height", `${height}px`);
322
+ }
323
+ measure();
324
+ requestAnimationFrame(measure);
325
+ }
326
+ return /* @__PURE__ */ jsx(Presence2, {
327
+ present: () => api.open.value,
328
+ children: /* @__PURE__ */ jsx("div", {
329
+ "data-slot": "collapsible-content",
330
+ "data-state": stateAttr,
331
+ class: () => _$unwrap(props).class,
332
+ ref: bindContent,
333
+ children: () => _$unwrap(props).children
334
+ })
335
+ });
336
+ });
337
+ var PopoverKey2 = Symbol("sinwan-ui.popover");
338
+ var PopoverRoot2 = cc((props) => {
339
+ const api = createOpenState(props);
340
+ provide(PopoverKey2, {
341
+ ...api,
342
+ placement: props.placement ?? "bottom",
343
+ align: props.align ?? "center"
344
+ });
345
+ return /* @__PURE__ */ jsx(Fragment, {
346
+ children: () => _$unwrap(props).children
347
+ });
348
+ });
349
+ var PopoverTrigger2 = cc((props) => {
350
+ const api = inject(PopoverKey2);
351
+ function onClick() {
352
+ api.setOpen(!api.open.value);
353
+ }
354
+ const ref = (el) => {
355
+ api.triggerEl.value = el;
356
+ };
357
+ if (props.asChild) {
358
+ return /* @__PURE__ */ jsx(Slot2, {
359
+ class: () => _$unwrap(props).class,
360
+ onclick: onClick,
361
+ ref,
362
+ children: () => _$unwrap(props).children
363
+ });
364
+ }
365
+ return _$createTemplate(_$tmpl_4, [
366
+ () => _$unwrap(props).class,
367
+ function expanded() {
368
+ return api.open.value;
369
+ },
370
+ onClick,
371
+ ref,
372
+ () => _$unwrap(props).children
373
+ ]);
374
+ });
375
+ var PopoverContent2 = cc((props) => {
376
+ const api = inject(PopoverKey2);
377
+ const contentEl = signal(null);
378
+ const { style, side: resolvedSide } = useAnchorPosition2({
379
+ open: api.open,
380
+ trigger: api.triggerEl,
381
+ content: contentEl,
382
+ placement: props.side ?? api.placement,
383
+ align: props.align ?? api.align,
384
+ gap: props.sideOffset === undefined ? 8 : props.sideOffset,
385
+ fallbackSize: { width: 240, height: 160 }
386
+ });
387
+ onMounted(() => {
388
+ function onDoc(e) {
389
+ if (!api.open.value)
390
+ return;
391
+ const t = e.target;
392
+ if (t instanceof Node && api.triggerEl.value?.contains(t) || isDismissExemptPointerTarget2(t)) {
393
+ return;
394
+ }
395
+ api.setOpen(false);
396
+ }
397
+ function onKey(e) {
398
+ if (e.key === "Escape") {
399
+ api.setOpen(false);
400
+ }
401
+ }
402
+ document.addEventListener("pointerdown", onDoc);
403
+ document.addEventListener("keydown", onKey);
404
+ onUnmounted(() => {
405
+ document.removeEventListener("pointerdown", onDoc);
406
+ document.removeEventListener("keydown", onKey);
407
+ });
408
+ });
409
+ function popoverState() {
410
+ return api.open.value ? "open" : "closed";
411
+ }
412
+ return /* @__PURE__ */ jsx(Presence2, {
413
+ present: () => api.open.value,
414
+ children: /* @__PURE__ */ jsx(UiPortal2, {
415
+ children: /* @__PURE__ */ jsx("div", {
416
+ "data-slot": "popover-content",
417
+ "data-state": popoverState,
418
+ "data-side": () => resolvedSide.value,
419
+ class: () => _$unwrap(props).class,
420
+ style: () => style.value,
421
+ role: "dialog",
422
+ onmouseenter: props.onmouseenter,
423
+ onmouseleave: props.onmouseleave,
424
+ ref: (el) => {
425
+ contentEl.value = el;
426
+ },
427
+ children: () => _$unwrap(props).children
428
+ })
429
+ })
430
+ });
431
+ });
432
+ var TooltipKey2 = Symbol("sinwan-ui.tooltip");
433
+ var TooltipProvider2 = cc((props) => {
434
+ props.delayDuration;
435
+ return props.children ?? null;
436
+ });
437
+ var TooltipRoot2 = cc((props) => {
438
+ const api = createOpenState(props);
439
+ provide(TooltipKey2, api);
440
+ return /* @__PURE__ */ jsx(Fragment, {
441
+ children: () => _$unwrap(props).children
442
+ });
443
+ });
444
+ var TooltipTrigger2 = cc((props) => {
445
+ const api = inject(TooltipKey2);
446
+ const show = () => {
447
+ api.setOpen(true);
448
+ };
449
+ const hide = () => {
450
+ api.setOpen(false);
451
+ };
452
+ const ref = (el) => {
453
+ api.triggerEl.value = el;
454
+ };
455
+ const handlers = {
456
+ onmouseenter: show,
457
+ onmouseleave: hide,
458
+ onfocus: show,
459
+ onblur: hide,
460
+ ref
461
+ };
462
+ if (props.asChild) {
463
+ return /* @__PURE__ */ jsx(Slot2, {
464
+ class: () => _$unwrap(props).class,
465
+ ...handlers,
466
+ children: () => _$unwrap(props).children
467
+ });
468
+ }
469
+ return /* @__PURE__ */ jsx("button", {
470
+ type: "button",
471
+ class: () => _$unwrap(props).class,
472
+ "data-slot": "tooltip-trigger",
473
+ ...handlers,
474
+ children: () => _$unwrap(props).children
475
+ });
476
+ });
477
+ var TooltipContent2 = cc((props) => {
478
+ const api = inject(TooltipKey2);
479
+ const contentEl = signal(null);
480
+ const { style, side: resolvedSide } = useAnchorPosition2({
481
+ open: api.open,
482
+ trigger: api.triggerEl,
483
+ content: contentEl,
484
+ placement: props.side === undefined ? "top" : props.side,
485
+ align: "center",
486
+ gap: props.sideOffset === undefined ? 8 : props.sideOffset,
487
+ fallbackSize: { width: 120, height: 32 }
488
+ });
489
+ function tooltipState() {
490
+ return api.open.value ? "open" : "closed";
491
+ }
492
+ return /* @__PURE__ */ jsx(Presence2, {
493
+ present: () => api.open.value,
494
+ children: /* @__PURE__ */ jsx(UiPortal2, {
495
+ children: /* @__PURE__ */ jsx("div", {
496
+ role: "tooltip",
497
+ "data-slot": "tooltip-content",
498
+ "data-state": tooltipState,
499
+ "data-side": () => resolvedSide.value,
500
+ class: () => _$unwrap(props).class,
501
+ style: () => style.value,
502
+ ref: (el) => {
503
+ contentEl.value = el;
504
+ },
505
+ children: () => _$unwrap(props).children
506
+ })
507
+ })
508
+ });
509
+ });
510
+
511
+ export { DialogKey2, DialogRoot2, DialogTrigger2, DialogClose2, DialogOverlay2, DialogContent2, CollapsibleKey2, CollapsibleRoot2, CollapsibleTrigger2, CollapsibleContent2, PopoverKey2, PopoverRoot2, PopoverTrigger2, PopoverContent2, TooltipKey2, TooltipProvider2, TooltipRoot2, TooltipTrigger2, TooltipContent2 };
@@ -0,0 +1,31 @@
1
+ // src/dismiss.ts
2
+ var DISMISS_EXEMPT_SELECTOR = [
3
+ "[data-slot$='-menu-content']",
4
+ "[data-slot='menubar-content']",
5
+ "[data-slot$='-sub-content']",
6
+ "[data-slot='select-content']",
7
+ "[data-slot='popover-content']",
8
+ "[data-slot='dialog-content']",
9
+ "[data-slot='alert-dialog-content']",
10
+ "[data-slot='sheet-content']",
11
+ "[data-slot='drawer-content']",
12
+ "[data-slot$='-overlay']",
13
+ "select",
14
+ "option",
15
+ "optgroup"
16
+ ].join(",");
17
+ function isDismissExemptPointerTarget2(target) {
18
+ if (target == null)
19
+ return false;
20
+ let el = null;
21
+ if (target instanceof Element) {
22
+ el = target;
23
+ } else if (target instanceof Node) {
24
+ el = target.parentElement;
25
+ }
26
+ if (el == null)
27
+ return false;
28
+ return el.closest(DISMISS_EXEMPT_SELECTOR) != null;
29
+ }
30
+
31
+ export { isDismissExemptPointerTarget2 };