@marimo-team/frontend 0.23.1-dev2 → 0.23.1-dev3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{CellStatus-CNNGwOIK.js → CellStatus-1vKptZLk.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-CfU-ThkK.js → ConnectedDataExplorerComponent-B0Mh-Jhz.js} +1 -1
- package/dist/assets/{ErrorBoundary-dxChUL02.js → ErrorBoundary-CxTq44MI.js} +1 -1
- package/dist/assets/{ImperativeModal-DoGv2BXV.js → ImperativeModal-hsPVDTG-.js} +1 -1
- package/dist/assets/{JsonOutput-D_ORGqdz.js → JsonOutput-BsAmBgmA.js} +1 -1
- package/dist/assets/{LazyAnyLanguageCodeMirror-CoYqQxHb.js → LazyAnyLanguageCodeMirror-CsrwfW0n.js} +2 -2
- package/dist/assets/{MarimoErrorOutput-Bc9JufDr.js → MarimoErrorOutput-BrEeS6om.js} +1 -1
- package/dist/assets/{RSPContexts-LWFBF00h.js → RSPContexts-DzigvqmT.js} +1 -1
- package/dist/assets/{RenderHTML-0dk6-mYI.js → RenderHTML-DvfCr2Ox.js} +1 -1
- package/dist/assets/{add-cell-with-ai-3_AIzd22.js → add-cell-with-ai-Dt7oHdbm.js} +1 -1
- package/dist/assets/{add-connection-dialog-DGgtN73u.js → add-connection-dialog-CspEHMf4.js} +1 -1
- package/dist/assets/{agent-panel-D7gqlew5.js → agent-panel-BnU7gQWx.js} +1 -1
- package/dist/assets/{ai-model-dropdown-DWOGmhDj.js → ai-model-dropdown-Xik-y-L5.js} +1 -1
- package/dist/assets/{alert-dialog-CXspBRlP.js → alert-dialog-C2mTH3GM.js} +1 -1
- package/dist/assets/{any-language-editor-DYgTL8eG.js → any-language-editor-DkEDDsUJ.js} +1 -1
- package/dist/assets/{app-config-button-BxCSZCVS.js → app-config-button-CHBHFhjc.js} +1 -1
- package/dist/assets/button-COIw2x9i.js +1 -0
- package/dist/assets/{cache-panel-8E_Y5OSb.js → cache-panel-C3V9UubH.js} +1 -1
- package/dist/assets/{cell-editor-B2IIBFCB.js → cell-editor-D_3l2zTD.js} +1 -1
- package/dist/assets/{cell-link-CcAqXeeg.js → cell-link-DJVe6_Zu.js} +1 -1
- package/dist/assets/{cells-EJo3u4za.js → cells-S7rO4svP.js} +1 -1
- package/dist/assets/{chat-display-DFUo2Riv.js → chat-display-CfEsEqVW.js} +1 -1
- package/dist/assets/{chat-panel-Dl4jq1Dp.js → chat-panel-qK2fGD8c.js} +1 -1
- package/dist/assets/{chat-ui-CysJeVE6.js → chat-ui-D0Zk2tGi.js} +1 -1
- package/dist/assets/{column-preview-DQBtRWJG.js → column-preview-BZ6dVJcf.js} +1 -1
- package/dist/assets/{command-DvF_4mQa.js → command-DnzBp4l4.js} +1 -1
- package/dist/assets/{command-palette-BCrWwbIt.js → command-palette-1FgTXBti.js} +1 -1
- package/dist/assets/{common-Bty2yo-n.js → common-BmgcLq5w.js} +1 -1
- package/dist/assets/{components-Dh-L-jYg.js → components-B_dPGsbP.js} +1 -1
- package/dist/assets/{components-B8TZ_vT_.js → components-D2yZZbqm.js} +1 -1
- package/dist/assets/{copy-icon-BGs1Pbai.js → copy-icon-Ci08KCdY.js} +1 -1
- package/dist/assets/{datasource-DY0N42ZB.js → datasource-t6MwjjVj.js} +1 -1
- package/dist/assets/{dependency-graph-panel-C23HsAdh.js → dependency-graph-panel-BadtKupA.js} +1 -1
- package/dist/assets/{dialog-BYjetQgE.js → dialog-H-hXtEOq.js} +1 -1
- package/dist/assets/{documentation-panel-okcEKCQM.js → documentation-panel-BsLlmX7w.js} +1 -1
- package/dist/assets/{download-TSo32ofd.js → download-Do1WPYs4.js} +1 -1
- package/dist/assets/{edit-page-fl9KJOcI.js → edit-page-CSyxrzTp.js} +3 -3
- package/dist/assets/{error-banner-bXc_9BBZ.js → error-banner-frvr6JXK.js} +1 -1
- package/dist/assets/{error-panel-aq2j0jIa.js → error-panel-CBVjdcTs.js} +1 -1
- package/dist/assets/{field-DTzXkFLZ.js → field-DaQqUJ5I.js} +1 -1
- package/dist/assets/{file-explorer-panel-bcSqGkbZ.js → file-explorer-panel-DYR37L0M.js} +1 -1
- package/dist/assets/{file-icons-DBaXCICA.js → file-icons-Ce885dch.js} +1 -1
- package/dist/assets/{floating-outline-BTmyhMGv.js → floating-outline-x0sdO8LG.js} +1 -1
- package/dist/assets/{focus-DXeddo75.js → focus-DTtb8f52.js} +1 -1
- package/dist/assets/{form-30oC5z9y.js → form-D_Nha4Lp.js} +1 -1
- package/dist/assets/{gallery-page-XSrY7bw_.js → gallery-page-BDI9wEUZ.js} +1 -1
- package/dist/assets/{glide-data-editor-Bd4FOxvW.js → glide-data-editor-QI6B6uKw.js} +1 -1
- package/dist/assets/{globals-DQM2RvzM.js → globals-Bu6OEURn.js} +1 -1
- package/dist/assets/{home-page-CruHjoHv.js → home-page-CoJ_ZMWR.js} +1 -1
- package/dist/assets/{hooks-DLUrd-jH.js → hooks-Cx6iKOXA.js} +1 -1
- package/dist/assets/{html-to-image-BJiJlwQY.js → html-to-image-B2vXpMPW.js} +1 -1
- package/dist/assets/{index-DTBKKey_.js → index-B_D5e64b.js} +6 -6
- package/dist/assets/{input-Bg12i6qY.js → input-DNCT6U6R.js} +1 -1
- package/dist/assets/{kiosk-mode-JCcLyeoQ.js → kiosk-mode-FcVQMZAH.js} +1 -1
- package/dist/assets/{layout-cq-nxDfO.js → layout-DW9T7Upe.js} +3 -3
- package/dist/assets/{logs-panel-BzhPrie8.js → logs-panel-Dsopo0A4.js} +1 -1
- package/dist/assets/{markdown-renderer-B9RsGqHb.js → markdown-renderer-Ds5PRrQP.js} +1 -1
- package/dist/assets/{mermaid-BJFSZcG6.js → mermaid-BPufPrIN.js} +1 -1
- package/dist/assets/{name-cell-input-CYsY4A1G.js → name-cell-input-CYTm4rHn.js} +1 -1
- package/dist/assets/{outline-panel-BCAWCKi6.js → outline-panel-C6Gebwlt.js} +1 -1
- package/dist/assets/{packages-panel-DxS7zji3.js → packages-panel-Cx5Im5-h.js} +1 -1
- package/dist/assets/{panels-B5BFPT3k.js → panels-CDCHQBRn.js} +1 -1
- package/dist/assets/{process-output-DqiZsqG9.js → process-output-DxNLeVL1.js} +1 -1
- package/dist/assets/{readonly-python-code-D8ITm60r.js → readonly-python-code-CB7U_Wc5.js} +1 -1
- package/dist/assets/{run-page-CI2eOA-G.js → run-page-CGoGL9nm.js} +1 -1
- package/dist/assets/{scratchpad-panel-Dwp8-2S1.js → scratchpad-panel-DR4mmtqX.js} +1 -1
- package/dist/assets/{secrets-panel-C6X5jB8Q.js → secrets-panel-DWMqzwkS.js} +1 -1
- package/dist/assets/{select--zcABebs.js → select-BwwUWhww.js} +1 -1
- package/dist/assets/{session-panel-ryqVmqVd.js → session-panel-DGqZrbYK.js} +1 -1
- package/dist/assets/{slides-component-DXMG6OXG.js → slides-component-BIXn0Nqk.js} +1 -1
- package/dist/assets/{snippets-panel--mh2FUXA.js → snippets-panel-CU_AkTo5.js} +1 -1
- package/dist/assets/{state-CMxx6hcP.js → state-Di6_R3-d.js} +1 -1
- package/dist/assets/{state-BDrig0S2.js → state-iGDxMYGl.js} +1 -1
- package/dist/assets/{switch-C6xjg01T.js → switch-YkPg_CVc.js} +1 -1
- package/dist/assets/{textarea-Cfp3upzK.js → textarea-cV4DzEoq.js} +1 -1
- package/dist/assets/{tracing-BExYhl1z.js → tracing-6MHdsIto.js} +1 -1
- package/dist/assets/{tracing-panel-Co5DeX-F.js → tracing-panel-Cwuf0kYN.js} +2 -2
- package/dist/assets/{useAddCell-BaTlDxTu.js → useAddCell-DDDgUZhC.js} +1 -1
- package/dist/assets/{useBoolean-BvsK1Xcs.js → useBoolean-Dk1Mb_so.js} +1 -1
- package/dist/assets/{useCellActionButton-DftkIqUl.js → useCellActionButton-BceYv-6H.js} +1 -1
- package/dist/assets/{useDeleteCell-d6yWnL3H.js → useDeleteCell-CwBNr3-p.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-BaVcOBM4.js → useDependencyPanelTab-Bjv6Z79M.js} +1 -1
- package/dist/assets/{useNotebookActions-D8Dm93y8.js → useNotebookActions-0DS32qpY.js} +1 -1
- package/dist/assets/{useRunCells-d2edY6Tu.js → useRunCells-Bf82xWy5.js} +1 -1
- package/dist/assets/{useSplitCell-DOiFyMgH.js → useSplitCell-WZ71D3bV.js} +1 -1
- package/dist/assets/{vega-component-CiVPyAwP.js → vega-component-DtSTT5wO.js} +1 -1
- package/dist/assets/{write-secret-modal-CHfFN0H8.js → write-secret-modal-CInxHVWJ.js} +1 -1
- package/dist/index.html +38 -38
- package/package.json +1 -1
- package/src/components/ui/button.tsx +1 -2
- package/src/utils/__tests__/events.test.ts +223 -0
- package/src/utils/events.ts +28 -14
- package/dist/assets/button-BKVLeSTX.js +0 -1
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
import { Events } from "../events";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Create a minimal fake event with just a target (no composedPath).
|
|
8
|
+
* Simulates synthetic events from libraries like React Aria.
|
|
9
|
+
*/
|
|
10
|
+
function fakeEvent(target: EventTarget): Pick<Event, "target"> {
|
|
11
|
+
return { target };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create a fake native-like KeyboardEvent with composedPath() returning
|
|
16
|
+
* a different element than target — the key scenario for shadow DOM
|
|
17
|
+
* retargeting where target is the shadow host but composedPath()[0]
|
|
18
|
+
* is the real focused element inside the shadow root.
|
|
19
|
+
*/
|
|
20
|
+
function fakeNativeEvent(
|
|
21
|
+
retargetedHost: EventTarget,
|
|
22
|
+
realTarget: EventTarget,
|
|
23
|
+
): KeyboardEvent {
|
|
24
|
+
const event = new KeyboardEvent("keydown");
|
|
25
|
+
Object.defineProperty(event, "target", { value: retargetedHost });
|
|
26
|
+
Object.defineProperty(event, "composedPath", {
|
|
27
|
+
value: () => [realTarget, retargetedHost, document.body, document],
|
|
28
|
+
});
|
|
29
|
+
return event;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe("Events.composedTarget", () => {
|
|
33
|
+
test("returns composedPath()[0] for native events", () => {
|
|
34
|
+
const input = document.createElement("input");
|
|
35
|
+
const host = document.createElement("div");
|
|
36
|
+
const event = fakeNativeEvent(host, input);
|
|
37
|
+
|
|
38
|
+
expect(Events.composedTarget(event)).toBe(input);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("falls back to e.target when composedPath is absent", () => {
|
|
42
|
+
const div = document.createElement("div");
|
|
43
|
+
const event = fakeEvent(div);
|
|
44
|
+
|
|
45
|
+
expect(Events.composedTarget(event)).toBe(div);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("falls back to e.target when composedPath returns empty array", () => {
|
|
49
|
+
const div = document.createElement("div");
|
|
50
|
+
const event = new KeyboardEvent("keydown");
|
|
51
|
+
Object.defineProperty(event, "target", { value: div });
|
|
52
|
+
Object.defineProperty(event, "composedPath", { value: () => [] });
|
|
53
|
+
|
|
54
|
+
expect(Events.composedTarget(event)).toBe(div);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("Events.shouldIgnoreKeyboardEvent", () => {
|
|
59
|
+
test("ignores events from <input>", () => {
|
|
60
|
+
const input = document.createElement("input");
|
|
61
|
+
const event = fakeNativeEvent(input, input);
|
|
62
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("ignores events from <textarea>", () => {
|
|
66
|
+
const textarea = document.createElement("textarea");
|
|
67
|
+
const event = fakeNativeEvent(textarea, textarea);
|
|
68
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("ignores events from <select>", () => {
|
|
72
|
+
const select = document.createElement("select");
|
|
73
|
+
const event = fakeNativeEvent(select, select);
|
|
74
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("ignores events from <button>", () => {
|
|
78
|
+
const button = document.createElement("button");
|
|
79
|
+
const event = fakeNativeEvent(button, button);
|
|
80
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("ignores events from contentEditable elements", () => {
|
|
84
|
+
const div = document.createElement("div");
|
|
85
|
+
div.setAttribute("contenteditable", "true");
|
|
86
|
+
document.body.append(div);
|
|
87
|
+
|
|
88
|
+
const event = fakeNativeEvent(div, div);
|
|
89
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
90
|
+
|
|
91
|
+
div.remove();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("ignores events from elements with role='textbox'", () => {
|
|
95
|
+
const container = document.createElement("div");
|
|
96
|
+
container.setAttribute("role", "textbox");
|
|
97
|
+
const child = document.createElement("span");
|
|
98
|
+
container.append(child);
|
|
99
|
+
document.body.append(container);
|
|
100
|
+
|
|
101
|
+
const event = fakeNativeEvent(child, child);
|
|
102
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
103
|
+
|
|
104
|
+
container.remove();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("ignores events from inside .cm-editor", () => {
|
|
108
|
+
const editor = document.createElement("div");
|
|
109
|
+
editor.className = "cm-editor";
|
|
110
|
+
const line = document.createElement("div");
|
|
111
|
+
editor.append(line);
|
|
112
|
+
document.body.append(editor);
|
|
113
|
+
|
|
114
|
+
const event = fakeNativeEvent(line, line);
|
|
115
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
116
|
+
|
|
117
|
+
editor.remove();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("does NOT ignore events from a plain <div>", () => {
|
|
121
|
+
const div = document.createElement("div");
|
|
122
|
+
const event = fakeNativeEvent(div, div);
|
|
123
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe("shadow DOM retargeting (#4230)", () => {
|
|
127
|
+
test("ignores keydown when real target inside shadow root is <input>", () => {
|
|
128
|
+
const host = document.createElement("marimo-text");
|
|
129
|
+
const input = document.createElement("input");
|
|
130
|
+
// event.target is the shadow host, composedPath()[0] is the real input
|
|
131
|
+
const event = fakeNativeEvent(host, input);
|
|
132
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("ignores keydown when real target inside shadow root is <textarea>", () => {
|
|
136
|
+
const host = document.createElement("marimo-text-area");
|
|
137
|
+
const textarea = document.createElement("textarea");
|
|
138
|
+
const event = fakeNativeEvent(host, textarea);
|
|
139
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("ignores keydown when real target inside shadow root is <select>", () => {
|
|
143
|
+
const host = document.createElement("marimo-dropdown");
|
|
144
|
+
const select = document.createElement("select");
|
|
145
|
+
const event = fakeNativeEvent(host, select);
|
|
146
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("does NOT ignore when shadow DOM real target is a plain <div>", () => {
|
|
150
|
+
const host = document.createElement("marimo-output");
|
|
151
|
+
const div = document.createElement("div");
|
|
152
|
+
const event = fakeNativeEvent(host, div);
|
|
153
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("does NOT ignore events from non-marimo custom elements", () => {
|
|
158
|
+
const el = document.createElement("sl-input");
|
|
159
|
+
const event = fakeNativeEvent(el, el);
|
|
160
|
+
expect(Events.shouldIgnoreKeyboardEvent(event)).toBe(false);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe("Events.fromInput", () => {
|
|
165
|
+
test("returns true for <input>", () => {
|
|
166
|
+
const input = document.createElement("input");
|
|
167
|
+
expect(Events.fromInput(fakeEvent(input))).toBe(true);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("returns true for <textarea>", () => {
|
|
171
|
+
const textarea = document.createElement("textarea");
|
|
172
|
+
expect(Events.fromInput(fakeEvent(textarea))).toBe(true);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("returns true for marimo custom elements", () => {
|
|
176
|
+
const el = document.createElement("marimo-slider");
|
|
177
|
+
expect(Events.fromInput(fakeEvent(el))).toBe(true);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// jsdom does not implement isContentEditable, so this is tested
|
|
181
|
+
// via shouldIgnoreKeyboardEvent which has a closest() fallback.
|
|
182
|
+
test.skip("returns true for contentEditable", () => {
|
|
183
|
+
const div = document.createElement("div");
|
|
184
|
+
div.setAttribute("contenteditable", "true");
|
|
185
|
+
document.body.append(div);
|
|
186
|
+
|
|
187
|
+
expect(Events.fromInput(fakeEvent(div))).toBe(true);
|
|
188
|
+
|
|
189
|
+
div.remove();
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("returns false for plain <div>", () => {
|
|
193
|
+
const div = document.createElement("div");
|
|
194
|
+
expect(Events.fromInput(fakeEvent(div))).toBe(false);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("uses composedPath when available (shadow DOM)", () => {
|
|
198
|
+
const host = document.createElement("div");
|
|
199
|
+
const input = document.createElement("input");
|
|
200
|
+
const event = fakeNativeEvent(host, input);
|
|
201
|
+
expect(Events.fromInput(event)).toBe(true);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
describe("Events.fromCodeMirror", () => {
|
|
206
|
+
test("returns true when target is inside .cm-editor", () => {
|
|
207
|
+
const editor = document.createElement("div");
|
|
208
|
+
editor.className = "cm-editor";
|
|
209
|
+
const line = document.createElement("div");
|
|
210
|
+
editor.append(line);
|
|
211
|
+
document.body.append(editor);
|
|
212
|
+
|
|
213
|
+
expect(Events.fromCodeMirror(line)).toBe(true);
|
|
214
|
+
editor.remove();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("returns false when target is not inside .cm-editor", () => {
|
|
218
|
+
const div = document.createElement("div");
|
|
219
|
+
document.body.append(div);
|
|
220
|
+
expect(Events.fromCodeMirror(div)).toBe(false);
|
|
221
|
+
div.remove();
|
|
222
|
+
});
|
|
223
|
+
});
|
package/src/utils/events.ts
CHANGED
|
@@ -37,21 +37,20 @@ export const Events = {
|
|
|
37
37
|
* Returns true if the event is coming from a text input
|
|
38
38
|
*/
|
|
39
39
|
fromInput: (e: Pick<KeyboardEvent, "target">) => {
|
|
40
|
-
const target = e
|
|
40
|
+
const target = Events.composedTarget(e);
|
|
41
41
|
return (
|
|
42
42
|
target.tagName === "INPUT" ||
|
|
43
43
|
target.tagName === "TEXTAREA" ||
|
|
44
44
|
target.tagName.startsWith("MARIMO") ||
|
|
45
45
|
target.isContentEditable ||
|
|
46
|
-
Events.fromCodeMirror(
|
|
46
|
+
Events.fromCodeMirror(target)
|
|
47
47
|
);
|
|
48
48
|
},
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Returns true if the event is coming from a code editor.
|
|
52
52
|
*/
|
|
53
|
-
fromCodeMirror: (
|
|
54
|
-
const target = e.target as HTMLElement;
|
|
53
|
+
fromCodeMirror: (target: HTMLElement) => {
|
|
55
54
|
return target.closest(".cm-editor") !== null;
|
|
56
55
|
},
|
|
57
56
|
|
|
@@ -60,20 +59,35 @@ export const Events = {
|
|
|
60
59
|
* form element or code editor.
|
|
61
60
|
*/
|
|
62
61
|
shouldIgnoreKeyboardEvent(e: KeyboardEvent) {
|
|
63
|
-
|
|
62
|
+
const target = Events.composedTarget(e);
|
|
64
63
|
return (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
(
|
|
69
|
-
(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
target instanceof HTMLInputElement ||
|
|
65
|
+
target instanceof HTMLTextAreaElement ||
|
|
66
|
+
target instanceof HTMLSelectElement ||
|
|
67
|
+
(target instanceof HTMLElement &&
|
|
68
|
+
(target.isContentEditable ||
|
|
69
|
+
target.tagName === "BUTTON" ||
|
|
70
|
+
target.closest("[role='textbox']") !== null ||
|
|
71
|
+
target.closest("[contenteditable='true']") !== null ||
|
|
72
|
+
Events.fromCodeMirror(target)))
|
|
74
73
|
);
|
|
75
74
|
},
|
|
76
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Resolve the real event target, piercing shadow DOM retargeting.
|
|
78
|
+
* Falls back to e.target for synthetic events (e.g. React Aria)
|
|
79
|
+
* that don't expose composedPath.
|
|
80
|
+
*
|
|
81
|
+
* Without this, e.target is the shadow host (e.g. <marimo-text>) rather than the
|
|
82
|
+
* real <input> inside it, so instanceof checks fail. (#4230)
|
|
83
|
+
*/
|
|
84
|
+
composedTarget(e: Pick<Event, "target">): HTMLElement {
|
|
85
|
+
if ("composedPath" in e && typeof e.composedPath === "function") {
|
|
86
|
+
return (e.composedPath()[0] ?? e.target) as HTMLElement;
|
|
87
|
+
}
|
|
88
|
+
return e.target as HTMLElement;
|
|
89
|
+
},
|
|
90
|
+
|
|
77
91
|
hasModifier: (
|
|
78
92
|
e: Pick<KeyboardEvent, "ctrlKey" | "metaKey" | "altKey" | "shiftKey">,
|
|
79
93
|
) => {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as p}from"./chunk-LvLJmgfZ.js";import{t as T}from"./react-Bj1aDYRI.js";import{t as M}from"./compiler-runtime-B3qBwwSJ.js";import{h as N,n as K,t as C}from"./useEventListener-DGjKht0c.js";import{n as I,t as o}from"./cn-DYvqRARy.js";import{t as H}from"./jsx-runtime-Blw4afVn.js";const m={stopPropagation:e=>t=>{t.stopPropagation(),e&&e(t)},onEnter:e=>t=>{t.key==="Enter"&&e&&e(t)},preventFocus:e=>{e.preventDefault()},fromInput:e=>{let t=e.target;return t.tagName==="INPUT"||t.tagName==="TEXTAREA"||t.tagName.startsWith("MARIMO")||t.isContentEditable||m.fromCodeMirror(e)},fromCodeMirror:e=>e.target.closest(".cm-editor")!==null,shouldIgnoreKeyboardEvent(e){return e.target instanceof HTMLInputElement||e.target instanceof HTMLTextAreaElement||e.target instanceof HTMLSelectElement||e.target instanceof HTMLElement&&(e.target.isContentEditable||e.target.tagName==="BUTTON"||e.target.closest("[role='textbox']")!==null||e.target.closest("[contenteditable='true']")!==null||e.target.closest(".cm-editor")!==null)},hasModifier:e=>e.ctrlKey||e.metaKey||e.altKey||e.shiftKey,isMetaOrCtrl:e=>e.metaKey||e.ctrlKey};var S=M(),v=p(T(),1),z=p(H(),1),a="active:shadow-none",x=I(o("disabled:opacity-50 disabled:pointer-events-none","inline-flex items-center justify-center rounded-md text-sm font-medium focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2 ring-offset-background"),{variants:{variant:{default:o("bg-primary text-primary-foreground hover:bg-primary/90 shadow-xs border border-primary",a),destructive:o("border shadow-xs","bg-(--red-9) hover:bg-(--red-10) dark:bg-(--red-6) dark:hover:bg-(--red-7)","text-(--red-1) dark:text-(--red-12)","border-(--red-11)",a),success:o("border shadow-xs","bg-(--grass-9) hover:bg-(--grass-10) dark:bg-(--grass-6) dark:hover:bg-(--grass-7)","text-(--grass-1) dark:text-(--grass-12)","border-(--grass-11)",a),warn:o("border shadow-xs","bg-(--yellow-9) hover:bg-(--yellow-10) dark:bg-(--yellow-6) dark:hover:bg-(--yellow-7)","text-(--yellow-12)","border-(--yellow-11)",a),action:o("bg-action text-action-foreground shadow-xs","hover:bg-action-hover border border-action",a),outline:o("border border-slate-300 shadow-xs","hover:bg-accent hover:text-accent-foreground","hover:border-primary","aria-selected:text-accent-foreground aria-selected:border-primary",a),secondary:o("bg-secondary text-secondary-foreground hover:bg-secondary/80","border border-input shadow-xs",a),text:o("opacity-80 hover:opacity-100","active:opacity-100"),ghost:o("border border-transparent","hover:bg-accent hover:text-accent-foreground hover:shadow-xs",a,"active:text-accent-foreground"),link:"underline-offset-4 hover:underline text-link",linkDestructive:"underline-offset-4 hover:underline text-destructive underline-destructive",outlineDestructive:"border border-destructive text-destructive hover:bg-destructive/10"},size:{default:"h-10 py-2 px-4",xs:"h-7 px-2 rounded-md text-xs",sm:"h-9 px-3 rounded-md",lg:"h-11 px-8 rounded-md",icon:"h-6 w-6 mb-0"},disabled:{true:"opacity-50 pointer-events-none"}},defaultVariants:{variant:"default",size:"sm"}}),y=v.forwardRef((e,t)=>{let r=(0,S.c)(7),{className:f,variant:w,size:k,asChild:h,keyboardShortcut:n,...d}=e,E=h===void 0?!1:h,s=v.useRef(null),i;r[0]===Symbol.for("react.memo_cache_sentinel")?(i=()=>s.current,r[0]=i):i=r[0],v.useImperativeHandle(t,i);let l;r[1]===n?l=r[2]:(l=u=>{n&&(m.shouldIgnoreKeyboardEvent(u)||N(n)(u)&&(u.preventDefault(),u.stopPropagation(),s!=null&&s.current&&!s.current.disabled&&s.current.click()))},r[1]=n,r[2]=l),C(document,"keydown",l);let g=E?K:"button",b=o(x({variant:w,size:k,className:f,disabled:d.disabled}),f),c;return r[3]!==g||r[4]!==d||r[5]!==b?(c=(0,z.jsx)(g,{className:b,ref:s,...d}),r[3]=g,r[4]=d,r[5]=b,r[6]=c):c=r[6],c});y.displayName="Button";export{x as n,m as r,y as t};
|