@panneau/ui 5.0.0-alpha.3 → 5.0.0-alpha.5
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 +2 -2
- package/dist/command-palette/CommandPalette.css +299 -0
- package/dist/command-palette/CommandPalette.d.ts +37 -0
- package/dist/command-palette/CommandPalette.d.ts.map +1 -0
- package/dist/command-palette/CommandPalette.js +194 -0
- package/dist/command-palette/CommandPalette.js.map +1 -0
- package/dist/command-palette/CommandPalette.module.js +62 -0
- package/dist/command-palette/CommandPalette.module.js.map +1 -0
- package/dist/command-palette/match.d.ts +39 -0
- package/dist/command-palette/match.d.ts.map +1 -0
- package/dist/command-palette/match.js +44 -0
- package/dist/command-palette/match.js.map +1 -0
- package/dist/command-palette/tokens.d.ts +3 -0
- package/dist/command-palette/tokens.d.ts.map +1 -0
- package/dist/command-palette/tokens.js +23 -0
- package/dist/command-palette/tokens.js.map +1 -0
- package/dist/command-palette/useCommandShortcut.d.ts +12 -0
- package/dist/command-palette/useCommandShortcut.d.ts.map +1 -0
- package/dist/command-palette/useCommandShortcut.js +29 -0
- package/dist/command-palette/useCommandShortcut.js.map +1 -0
- package/dist/date-picker/DatePicker.css +40 -0
- package/dist/date-picker/DatePicker.d.ts +2 -1
- package/dist/date-picker/DatePicker.d.ts.map +1 -1
- package/dist/date-picker/DatePicker.js +54 -8
- package/dist/date-picker/DatePicker.js.map +1 -1
- package/dist/date-picker/DatePicker.module.js +5 -1
- package/dist/date-picker/DatePicker.module.js.map +1 -1
- package/dist/dialog/Dialog.css +36 -2
- package/dist/dialog/Dialog.d.ts +15 -3
- package/dist/dialog/Dialog.d.ts.map +1 -1
- package/dist/dialog/Dialog.js +22 -14
- package/dist/dialog/Dialog.js.map +1 -1
- package/dist/dialog/Dialog.module.js +8 -2
- package/dist/dialog/Dialog.module.js.map +1 -1
- package/dist/dialog/tokens.d.ts +1 -1
- package/dist/dialog/tokens.d.ts.map +1 -1
- package/dist/dialog/tokens.js +2 -0
- package/dist/dialog/tokens.js.map +1 -1
- package/dist/field/Field.css +9 -0
- package/dist/field/Field.module.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/segmented-control/SegmentedControl.css +83 -0
- package/dist/segmented-control/SegmentedControl.d.ts +35 -0
- package/dist/segmented-control/SegmentedControl.d.ts.map +1 -0
- package/dist/segmented-control/SegmentedControl.js +44 -0
- package/dist/segmented-control/SegmentedControl.js.map +1 -0
- package/dist/segmented-control/SegmentedControl.module.js +16 -0
- package/dist/segmented-control/SegmentedControl.module.js.map +1 -0
- package/dist/segmented-control/tokens.d.ts +3 -0
- package/dist/segmented-control/tokens.d.ts.map +1 -0
- package/dist/segmented-control/tokens.js +29 -0
- package/dist/segmented-control/tokens.js.map +1 -0
- package/dist/select/ListBox.css +8 -1
- package/dist/select/ListBox.module.js +2 -2
- package/dist/select/ListBox.module.js.map +1 -1
- package/dist/select/listBoxTokens.d.ts +1 -1
- package/dist/select/listBoxTokens.d.ts.map +1 -1
- package/dist/select/listBoxTokens.js +2 -0
- package/dist/select/listBoxTokens.js.map +1 -1
- package/dist/text-input/TextInput.d.ts.map +1 -1
- package/dist/text-input/TextInput.js +2 -0
- package/dist/text-input/TextInput.js.map +1 -1
- package/dist/theme/components.d.ts +4 -2
- package/dist/theme/components.d.ts.map +1 -1
- package/dist/theme/components.js +4 -0
- package/dist/theme/components.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -290,11 +290,11 @@ The theme model is described in [decision 0024](../../docs/decisions/0024-theme-
|
|
|
290
290
|
|
|
291
291
|
## Primitives
|
|
292
292
|
|
|
293
|
-
`Heading`, `Text`, `Prose`, `Stack`, `Inline`, `Grid`, `Container`, `Divider`, `Button`, `IconButton`, `TextInput`, `TextArea`, `NumberInput`, `Select` (single or multiple), `ComboBox`, `Checkbox`, `Switch`, `RadioGroup`, `DatePicker`, `TimeInput`, `Fieldset`, `Dialog`, `Popover`, `Menu`, `Tabs`, `Tooltip`, toasts (`useToast()`), `Alert`, `Badge`, `Spinner`, `Card`, `Disclosure` and `Icon`.
|
|
293
|
+
`Heading`, `Text`, `Prose`, `Stack`, `Inline`, `Grid`, `Container`, `Divider`, `Button`, `IconButton`, `TextInput`, `TextArea`, `NumberInput`, `Select` (single or multiple), `ComboBox`, `Checkbox`, `Switch`, `RadioGroup`, `SegmentedControl`, `DatePicker`, `TimeInput`, `Fieldset`, `Dialog`, `Popover`, `Menu`, `Tabs`, `Tooltip`, toasts (`useToast()`), `Alert`, `Badge`, `Spinner`, `Card`, `Disclosure` and `Icon`.
|
|
294
294
|
|
|
295
295
|
- Every component accepts `className`, and `xxxClassName` props for its inner elements (`labelClassName`, `inputClassName`…).
|
|
296
296
|
- Labelled controls take `label`, `description` and `errors` (a list of messages: any message makes the control invalid and describes it).
|
|
297
|
-
- They work on phones: larger touch targets on touch screens, dialogs as bottom sheets, scrolling tabs.
|
|
297
|
+
- They work on phones: larger touch targets on touch screens, dialogs as bottom sheets (or the whole screen, with `fullScreenOnPhone`), scrolling tabs.
|
|
298
298
|
|
|
299
299
|
## Icons
|
|
300
300
|
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/* A dialog near the top of the screen: the search field over the results, and a footer with the
|
|
2
|
+
* count and the keys. The whole screen on a phone. */
|
|
3
|
+
|
|
4
|
+
.panneau-command-palette-overlay {
|
|
5
|
+
position: fixed;
|
|
6
|
+
inset: 0;
|
|
7
|
+
z-index: var(--panneau-z-overlay);
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: flex-start;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
padding: var(--panneau-command-palette-offset-top, 12dvh) var(--panneau-space-4)
|
|
12
|
+
var(--panneau-space-4);
|
|
13
|
+
background-color: var(--panneau-color-backdrop);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.panneau-command-palette-overlay[data-entering] {
|
|
17
|
+
animation: panneau-command-palette-fade var(--panneau-duration) ease-out;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.panneau-command-palette-modal {
|
|
21
|
+
display: flex;
|
|
22
|
+
width: 100%;
|
|
23
|
+
max-width: var(--panneau-command-palette-width, 40rem);
|
|
24
|
+
outline: none;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.panneau-command-palette-modal[data-entering] {
|
|
28
|
+
animation: panneau-command-palette-rise var(--panneau-duration) ease-out;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.panneau-command-palette-dialog {
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
width: 100%;
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
color: var(--panneau-color-text);
|
|
37
|
+
background-color: var(--panneau-command-palette-bg, var(--panneau-color-surface-raised));
|
|
38
|
+
border: var(--panneau-border-width) solid var(--panneau-color-border);
|
|
39
|
+
border-radius: var(--panneau-command-palette-radius, var(--panneau-radius-lg));
|
|
40
|
+
box-shadow: var(--panneau-shadow-lg);
|
|
41
|
+
outline: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.panneau-command-palette-field {
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
gap: var(--panneau-space-2);
|
|
48
|
+
padding: var(--panneau-space-3) var(--panneau-space-4);
|
|
49
|
+
border-bottom: var(--panneau-border-width) solid var(--panneau-color-border);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.panneau-command-palette-search {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex: 1 1 auto;
|
|
55
|
+
align-items: center;
|
|
56
|
+
gap: var(--panneau-space-2);
|
|
57
|
+
min-width: 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.panneau-command-palette-close {
|
|
61
|
+
display: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.panneau-command-palette-field-icon {
|
|
65
|
+
flex: none;
|
|
66
|
+
color: var(--panneau-color-text-muted);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* What the search is narrowed to, before the field. */
|
|
70
|
+
.panneau-command-palette-scope {
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
flex: none;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: var(--panneau-space-1);
|
|
75
|
+
max-width: 50%;
|
|
76
|
+
padding: 0 var(--panneau-space-1) 0 var(--panneau-space-2);
|
|
77
|
+
border-radius: var(--panneau-radius-full);
|
|
78
|
+
background-color: var(--panneau-color-surface-sunken);
|
|
79
|
+
font-size: var(--panneau-font-size-sm);
|
|
80
|
+
font-weight: var(--panneau-font-weight-medium);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.panneau-command-palette-scope-label {
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
text-overflow: ellipsis;
|
|
86
|
+
white-space: nowrap;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.panneau-command-palette-scope-remove {
|
|
90
|
+
display: inline-flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
padding: var(--panneau-space-1);
|
|
94
|
+
border: 0;
|
|
95
|
+
border-radius: var(--panneau-radius-full);
|
|
96
|
+
background: none;
|
|
97
|
+
color: var(--panneau-color-text-muted);
|
|
98
|
+
cursor: pointer;
|
|
99
|
+
outline: none;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.panneau-command-palette-scope-remove[data-hovered] {
|
|
103
|
+
color: var(--panneau-color-text);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.panneau-command-palette-scope-remove[data-focus-visible] {
|
|
107
|
+
outline: var(--panneau-focus-width) solid var(--panneau-color-focus);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.panneau-command-palette-input {
|
|
111
|
+
flex: 1 1 auto;
|
|
112
|
+
min-width: 0;
|
|
113
|
+
padding: var(--panneau-space-1) 0;
|
|
114
|
+
border: 0;
|
|
115
|
+
background: none;
|
|
116
|
+
color: inherit;
|
|
117
|
+
font: inherit;
|
|
118
|
+
font-size: var(--panneau-font-size-lg);
|
|
119
|
+
outline: none;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.panneau-command-palette-input::placeholder {
|
|
123
|
+
color: var(--panneau-color-text-muted);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* The browser's own clear button: Escape clears the field. */
|
|
127
|
+
.panneau-command-palette-input::-webkit-search-cancel-button {
|
|
128
|
+
appearance: none;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.panneau-command-palette-list {
|
|
132
|
+
display: flex;
|
|
133
|
+
flex-direction: column;
|
|
134
|
+
gap: var(--panneau-space-2);
|
|
135
|
+
max-height: var(--panneau-command-palette-list-max-height, 60dvh);
|
|
136
|
+
padding: var(--panneau-space-2);
|
|
137
|
+
overflow-y: auto;
|
|
138
|
+
outline: none;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.panneau-command-palette-group {
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-direction: column;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.panneau-command-palette-group-label {
|
|
147
|
+
padding: var(--panneau-space-1) var(--panneau-space-2);
|
|
148
|
+
color: var(--panneau-color-text-muted);
|
|
149
|
+
font-size: var(--panneau-font-size-xs);
|
|
150
|
+
font-weight: var(--panneau-font-weight-medium);
|
|
151
|
+
letter-spacing: 0.04em;
|
|
152
|
+
text-transform: uppercase;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.panneau-command-palette-item {
|
|
156
|
+
display: flex;
|
|
157
|
+
align-items: center;
|
|
158
|
+
gap: var(--panneau-space-3);
|
|
159
|
+
min-height: var(--panneau-control-height);
|
|
160
|
+
padding: var(--panneau-space-1) var(--panneau-space-2);
|
|
161
|
+
border-radius: var(--panneau-command-palette-item-radius, var(--panneau-radius-md));
|
|
162
|
+
color: var(--panneau-color-text);
|
|
163
|
+
text-decoration: none;
|
|
164
|
+
cursor: pointer;
|
|
165
|
+
outline: none;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.panneau-command-palette-item[data-focused],
|
|
169
|
+
.panneau-command-palette-item[data-hovered] {
|
|
170
|
+
background-color: var(--panneau-command-palette-item-active-bg, var(--panneau-color-hover));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.panneau-command-palette-item[data-focus-visible] {
|
|
174
|
+
box-shadow: inset 0 0 0 var(--panneau-focus-width) var(--panneau-color-focus);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.panneau-command-palette-icon,
|
|
178
|
+
.panneau-command-palette-image {
|
|
179
|
+
display: inline-grid;
|
|
180
|
+
flex: none;
|
|
181
|
+
place-items: center;
|
|
182
|
+
width: 2rem;
|
|
183
|
+
height: 2rem;
|
|
184
|
+
border-radius: var(--panneau-radius-sm);
|
|
185
|
+
color: var(--panneau-color-text-muted);
|
|
186
|
+
background-color: var(--panneau-color-surface-sunken);
|
|
187
|
+
object-fit: cover;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.panneau-command-palette-text {
|
|
191
|
+
display: flex;
|
|
192
|
+
flex-direction: column;
|
|
193
|
+
min-width: 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.panneau-command-palette-label,
|
|
197
|
+
.panneau-command-palette-description {
|
|
198
|
+
overflow: hidden;
|
|
199
|
+
text-overflow: ellipsis;
|
|
200
|
+
white-space: nowrap;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.panneau-command-palette-description {
|
|
204
|
+
color: var(--panneau-color-text-muted);
|
|
205
|
+
font-size: var(--panneau-font-size-sm);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.panneau-command-palette-empty {
|
|
209
|
+
margin: 0;
|
|
210
|
+
padding: var(--panneau-space-6) var(--panneau-space-2);
|
|
211
|
+
color: var(--panneau-color-text-muted);
|
|
212
|
+
text-align: center;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.panneau-command-palette-footer {
|
|
216
|
+
display: flex;
|
|
217
|
+
flex-wrap: wrap;
|
|
218
|
+
align-items: center;
|
|
219
|
+
justify-content: space-between;
|
|
220
|
+
gap: var(--panneau-space-2);
|
|
221
|
+
padding: var(--panneau-space-2) var(--panneau-space-4);
|
|
222
|
+
border-top: var(--panneau-border-width) solid var(--panneau-color-border);
|
|
223
|
+
color: var(--panneau-color-text-muted);
|
|
224
|
+
font-size: var(--panneau-font-size-xs);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.panneau-command-palette-hints {
|
|
228
|
+
display: flex;
|
|
229
|
+
gap: var(--panneau-space-3);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.panneau-command-palette-hint {
|
|
233
|
+
display: inline-flex;
|
|
234
|
+
align-items: center;
|
|
235
|
+
gap: var(--panneau-space-1);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.panneau-command-palette-key {
|
|
239
|
+
display: inline-grid;
|
|
240
|
+
place-items: center;
|
|
241
|
+
min-width: 1.25rem;
|
|
242
|
+
height: 1.25rem;
|
|
243
|
+
padding: 0 var(--panneau-space-1);
|
|
244
|
+
border: var(--panneau-border-width) solid var(--panneau-color-border);
|
|
245
|
+
border-radius: var(--panneau-radius-sm);
|
|
246
|
+
background: var(--panneau-color-surface);
|
|
247
|
+
font-family: inherit;
|
|
248
|
+
font-size: var(--panneau-font-size-xs);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
@keyframes panneau-command-palette-fade {
|
|
252
|
+
from {
|
|
253
|
+
opacity: 0;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@keyframes panneau-command-palette-rise {
|
|
258
|
+
from {
|
|
259
|
+
transform: translateY(-0.5rem);
|
|
260
|
+
opacity: 0;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* A phone: the whole screen, without the keys, which a touch screen has no use for. */
|
|
265
|
+
@container panneau-root (max-width: 40rem) {
|
|
266
|
+
.panneau-command-palette-overlay {
|
|
267
|
+
padding: 0;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.panneau-command-palette-modal {
|
|
271
|
+
max-width: none;
|
|
272
|
+
height: 100dvh;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.panneau-command-palette-dialog {
|
|
276
|
+
border: 0;
|
|
277
|
+
border-radius: 0;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.panneau-command-palette-list {
|
|
281
|
+
flex: 1 1 auto;
|
|
282
|
+
max-height: none;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.panneau-command-palette-hints {
|
|
286
|
+
display: none;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.panneau-command-palette-close {
|
|
290
|
+
display: inline-flex;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@media (prefers-reduced-motion: reduce) {
|
|
295
|
+
.panneau-command-palette-overlay[data-entering],
|
|
296
|
+
.panneau-command-palette-modal[data-entering] {
|
|
297
|
+
animation: none;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type CommandPaletteGroup } from './match';
|
|
3
|
+
export interface CommandPaletteProps {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
onOpenChange: (isOpen: boolean) => void;
|
|
6
|
+
/**
|
|
7
|
+
* The groups of items. The palette matches them with the query itself, except groups that
|
|
8
|
+
* are already `matched`, such as results of a server, which come after the others.
|
|
9
|
+
*/
|
|
10
|
+
groups: readonly CommandPaletteGroup[];
|
|
11
|
+
/** The query, controlled: to search a server with it. Empty each time the palette opens. */
|
|
12
|
+
inputValue?: string;
|
|
13
|
+
onInputChange?: (value: string) => void;
|
|
14
|
+
/** Accessible name of the palette and its field. Defaults to "Search". */
|
|
15
|
+
'aria-label'?: string;
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
/** A line under the results, and in place of them when there are none: loading or failed
|
|
18
|
+
* results of a server, a query too short to search. */
|
|
19
|
+
status?: ReactNode;
|
|
20
|
+
/**
|
|
21
|
+
* What the search is narrowed to, such as one resource, shown as a chip before the field.
|
|
22
|
+
* Backspace in the empty field, or the chip's button, calls `onScopeRemove`.
|
|
23
|
+
*/
|
|
24
|
+
scope?: string | null;
|
|
25
|
+
onScopeRemove?: () => void;
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A command palette: a search field over groups of items to go to or run, in a dialog near the top
|
|
30
|
+
* of the screen. Typing matches the items without case or accents, every word having to match,
|
|
31
|
+
* the best matches first. Arrow keys move through the items, Enter opens one and closes the
|
|
32
|
+
* palette, Escape clears the field, then closes it. A `scope` narrows what it searches, as a chip
|
|
33
|
+
* before the field. It knows no data or router: links go through
|
|
34
|
+
* the app's `RouterProvider`. `useCommandShortcut()` opens it with ⌘K or Ctrl+K.
|
|
35
|
+
*/
|
|
36
|
+
export declare function CommandPalette({ isOpen, onOpenChange, groups, inputValue: controlledValue, onInputChange, 'aria-label': ariaLabel, placeholder, status, scope, onScopeRemove, className, }: CommandPaletteProps): import("react").JSX.Element | null;
|
|
37
|
+
//# sourceMappingURL=CommandPalette.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette.d.ts","sourceRoot":"","sources":["../../src/command-palette/CommandPalette.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,OAAO,CAAC;AAuBjD,OAAO,EAAE,KAAK,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AAElE,MAAM,WAAW,mBAAmB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACvC,4FAA4F;IAC5F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;2DACuD;IACvD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAC3B,MAAM,EACN,YAAY,EACZ,MAAM,EACN,UAAU,EAAE,eAAe,EAC3B,aAAa,EACb,YAAY,EAAE,SAAS,EACvB,WAAW,EACX,MAAM,EACN,KAAY,EACZ,aAAa,EACb,SAAS,GACZ,EAAE,mBAAmB,sCA2KrB"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { cx } from "../utils/cx.js";
|
|
2
|
+
import { Icon } from "../icon/Icon.js";
|
|
3
|
+
import { messages } from "../intl/messages.js";
|
|
4
|
+
import { usePanneauIntl } from "../intl/usePanneauIntl.js";
|
|
5
|
+
import { usePortalContainer } from "../root/PanneauRoot.js";
|
|
6
|
+
import { IconButton } from "../icon-button/IconButton.js";
|
|
7
|
+
import CommandPalette_module_default from "./CommandPalette.module.js";
|
|
8
|
+
import { matchCommands } from "./match.js";
|
|
9
|
+
import { ArrowDownUp, CornerDownLeft, Search, X } from "lucide-react";
|
|
10
|
+
import { Autocomplete, Button, Dialog, Header, Input, Menu, MenuItem, MenuSection, Modal, ModalOverlay, SearchField, Text } from "react-aria-components";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
//#region src/command-palette/CommandPalette.tsx
|
|
14
|
+
/**
|
|
15
|
+
* A command palette: a search field over groups of items to go to or run, in a dialog near the top
|
|
16
|
+
* of the screen. Typing matches the items without case or accents, every word having to match,
|
|
17
|
+
* the best matches first. Arrow keys move through the items, Enter opens one and closes the
|
|
18
|
+
* palette, Escape clears the field, then closes it. A `scope` narrows what it searches, as a chip
|
|
19
|
+
* before the field. It knows no data or router: links go through
|
|
20
|
+
* the app's `RouterProvider`. `useCommandShortcut()` opens it with ⌘K or Ctrl+K.
|
|
21
|
+
*/
|
|
22
|
+
function CommandPalette({ isOpen, onOpenChange, groups, inputValue: controlledValue, onInputChange, "aria-label": ariaLabel, placeholder, status, scope = null, onScopeRemove, className }) {
|
|
23
|
+
const intl = usePanneauIntl();
|
|
24
|
+
const container = usePortalContainer();
|
|
25
|
+
const [uncontrolledValue, setUncontrolledValue] = useState("");
|
|
26
|
+
const value = controlledValue ?? uncontrolledValue;
|
|
27
|
+
const setValue = (next) => {
|
|
28
|
+
setUncontrolledValue(next);
|
|
29
|
+
onInputChange?.(next);
|
|
30
|
+
};
|
|
31
|
+
const label = ariaLabel ?? intl.formatMessage(messages.commandPalette);
|
|
32
|
+
const visible = matchCommands(groups, value, intl.locale);
|
|
33
|
+
const count = visible.reduce((total, group) => total + group.items.length, 0);
|
|
34
|
+
const changeOpen = (open) => {
|
|
35
|
+
if (!open) setValue("");
|
|
36
|
+
onOpenChange(open);
|
|
37
|
+
};
|
|
38
|
+
if (container === null) return null;
|
|
39
|
+
return /* @__PURE__ */ jsx(ModalOverlay, {
|
|
40
|
+
isOpen,
|
|
41
|
+
onOpenChange: changeOpen,
|
|
42
|
+
isDismissable: true,
|
|
43
|
+
className: CommandPalette_module_default.overlay,
|
|
44
|
+
UNSTABLE_portalContainer: container,
|
|
45
|
+
children: /* @__PURE__ */ jsx(Modal, {
|
|
46
|
+
className: CommandPalette_module_default.modal,
|
|
47
|
+
children: /* @__PURE__ */ jsxs(Dialog, {
|
|
48
|
+
"aria-label": label,
|
|
49
|
+
className: cx("panneau-command-palette", CommandPalette_module_default.dialog, className),
|
|
50
|
+
children: [/* @__PURE__ */ jsxs(Autocomplete, {
|
|
51
|
+
inputValue: value,
|
|
52
|
+
onInputChange: setValue,
|
|
53
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
54
|
+
className: CommandPalette_module_default.field,
|
|
55
|
+
children: [/* @__PURE__ */ jsxs(SearchField, {
|
|
56
|
+
"aria-label": scope !== null ? `${label}: ${scope}` : label,
|
|
57
|
+
autoFocus: true,
|
|
58
|
+
className: CommandPalette_module_default.search,
|
|
59
|
+
children: [
|
|
60
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
61
|
+
icon: Search,
|
|
62
|
+
size: "md",
|
|
63
|
+
className: CommandPalette_module_default.fieldIcon
|
|
64
|
+
}),
|
|
65
|
+
scope !== null ? /* @__PURE__ */ jsxs("span", {
|
|
66
|
+
className: CommandPalette_module_default.scope,
|
|
67
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
68
|
+
className: CommandPalette_module_default.scopeLabel,
|
|
69
|
+
children: scope
|
|
70
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
71
|
+
"aria-label": intl.formatMessage(messages.commandRemoveScope, { scope }),
|
|
72
|
+
className: CommandPalette_module_default.scopeRemove,
|
|
73
|
+
onPress: onScopeRemove,
|
|
74
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
75
|
+
icon: X,
|
|
76
|
+
size: "xs"
|
|
77
|
+
})
|
|
78
|
+
})]
|
|
79
|
+
}) : null,
|
|
80
|
+
/* @__PURE__ */ jsx(Input, {
|
|
81
|
+
placeholder: placeholder ?? label,
|
|
82
|
+
className: CommandPalette_module_default.input,
|
|
83
|
+
onKeyDown: (event) => {
|
|
84
|
+
if (event.key === "Backspace" && value === "" && scope !== null) {
|
|
85
|
+
event.preventDefault();
|
|
86
|
+
onScopeRemove?.();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
]
|
|
91
|
+
}), /* @__PURE__ */ jsx(IconButton, {
|
|
92
|
+
icon: X,
|
|
93
|
+
label: intl.formatMessage(messages.close),
|
|
94
|
+
size: "sm",
|
|
95
|
+
showTooltip: false,
|
|
96
|
+
className: CommandPalette_module_default.close,
|
|
97
|
+
onPress: () => changeOpen(false)
|
|
98
|
+
})]
|
|
99
|
+
}), /* @__PURE__ */ jsx(Menu, {
|
|
100
|
+
"aria-label": label,
|
|
101
|
+
className: CommandPalette_module_default.list,
|
|
102
|
+
renderEmptyState: () => /* @__PURE__ */ jsx("p", {
|
|
103
|
+
className: CommandPalette_module_default.empty,
|
|
104
|
+
children: status ?? intl.formatMessage(messages.commandResults, { count: 0 })
|
|
105
|
+
}),
|
|
106
|
+
children: visible.map((group_0) => /* @__PURE__ */ jsxs(MenuSection, {
|
|
107
|
+
id: group_0.id,
|
|
108
|
+
className: CommandPalette_module_default.group,
|
|
109
|
+
children: [/* @__PURE__ */ jsx(Header, {
|
|
110
|
+
className: CommandPalette_module_default.groupLabel,
|
|
111
|
+
children: group_0.label
|
|
112
|
+
}), group_0.items.map((item) => /* @__PURE__ */ jsxs(MenuItem, {
|
|
113
|
+
id: `${group_0.id}:${item.id}`,
|
|
114
|
+
textValue: item.label,
|
|
115
|
+
href: item.href,
|
|
116
|
+
onAction: () => {
|
|
117
|
+
item.onAction?.();
|
|
118
|
+
if (item.keepsOpen !== true) changeOpen(false);
|
|
119
|
+
},
|
|
120
|
+
className: CommandPalette_module_default.item,
|
|
121
|
+
children: [item.imageUrl !== void 0 ? /* @__PURE__ */ jsx("img", {
|
|
122
|
+
src: item.imageUrl,
|
|
123
|
+
alt: "",
|
|
124
|
+
className: CommandPalette_module_default.image
|
|
125
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
126
|
+
className: CommandPalette_module_default.icon,
|
|
127
|
+
"aria-hidden": "true",
|
|
128
|
+
children: item.icon !== void 0 ? /* @__PURE__ */ jsx(Icon, {
|
|
129
|
+
icon: item.icon,
|
|
130
|
+
size: "md"
|
|
131
|
+
}) : null
|
|
132
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
133
|
+
className: CommandPalette_module_default.text,
|
|
134
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
135
|
+
slot: "label",
|
|
136
|
+
className: CommandPalette_module_default.label,
|
|
137
|
+
children: item.label
|
|
138
|
+
}), item.description !== void 0 ? /* @__PURE__ */ jsx(Text, {
|
|
139
|
+
slot: "description",
|
|
140
|
+
className: CommandPalette_module_default.description,
|
|
141
|
+
children: item.description
|
|
142
|
+
}) : null]
|
|
143
|
+
})]
|
|
144
|
+
}, item.id))]
|
|
145
|
+
}, group_0.id))
|
|
146
|
+
})]
|
|
147
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
148
|
+
className: CommandPalette_module_default.footer,
|
|
149
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
150
|
+
className: CommandPalette_module_default.status,
|
|
151
|
+
role: "status",
|
|
152
|
+
children: status ?? intl.formatMessage(messages.commandResults, { count })
|
|
153
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
154
|
+
className: CommandPalette_module_default.hints,
|
|
155
|
+
"aria-hidden": "true",
|
|
156
|
+
children: [
|
|
157
|
+
/* @__PURE__ */ jsxs("span", {
|
|
158
|
+
className: CommandPalette_module_default.hint,
|
|
159
|
+
children: [/* @__PURE__ */ jsx("kbd", {
|
|
160
|
+
className: CommandPalette_module_default.key,
|
|
161
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
162
|
+
icon: ArrowDownUp,
|
|
163
|
+
size: "xs"
|
|
164
|
+
})
|
|
165
|
+
}), intl.formatMessage(messages.commandHintMove)]
|
|
166
|
+
}),
|
|
167
|
+
/* @__PURE__ */ jsxs("span", {
|
|
168
|
+
className: CommandPalette_module_default.hint,
|
|
169
|
+
children: [/* @__PURE__ */ jsx("kbd", {
|
|
170
|
+
className: CommandPalette_module_default.key,
|
|
171
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
172
|
+
icon: CornerDownLeft,
|
|
173
|
+
size: "xs"
|
|
174
|
+
})
|
|
175
|
+
}), intl.formatMessage(messages.commandHintOpen)]
|
|
176
|
+
}),
|
|
177
|
+
/* @__PURE__ */ jsxs("span", {
|
|
178
|
+
className: CommandPalette_module_default.hint,
|
|
179
|
+
children: [/* @__PURE__ */ jsx("kbd", {
|
|
180
|
+
className: CommandPalette_module_default.key,
|
|
181
|
+
children: "esc"
|
|
182
|
+
}), intl.formatMessage(messages.commandHintClose)]
|
|
183
|
+
})
|
|
184
|
+
]
|
|
185
|
+
})]
|
|
186
|
+
})]
|
|
187
|
+
})
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
//#endregion
|
|
192
|
+
export { CommandPalette };
|
|
193
|
+
|
|
194
|
+
//# sourceMappingURL=CommandPalette.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette.js","names":["group","styles"],"sources":["../../src/command-palette/CommandPalette.tsx"],"sourcesContent":["import { ArrowDownUp, CornerDownLeft, Search, X } from 'lucide-react';\nimport { type ReactNode, useState } from 'react';\nimport {\n Autocomplete,\n Button,\n Dialog,\n Header,\n Input,\n Menu,\n MenuItem,\n MenuSection,\n Modal,\n ModalOverlay,\n SearchField,\n Text,\n} from 'react-aria-components';\n\nimport { IconButton } from '../icon-button/IconButton';\nimport { Icon } from '../icon/Icon';\nimport { messages } from '../intl/messages';\nimport { usePanneauIntl } from '../intl/usePanneauIntl';\nimport { usePortalContainer } from '../root/PanneauRoot';\nimport { cx } from '../utils/cx';\nimport styles from './CommandPalette.module.css';\nimport { type CommandPaletteGroup, matchCommands } from './match';\n\nexport interface CommandPaletteProps {\n isOpen: boolean;\n onOpenChange: (isOpen: boolean) => void;\n /**\n * The groups of items. The palette matches them with the query itself, except groups that\n * are already `matched`, such as results of a server, which come after the others.\n */\n groups: readonly CommandPaletteGroup[];\n /** The query, controlled: to search a server with it. Empty each time the palette opens. */\n inputValue?: string;\n onInputChange?: (value: string) => void;\n /** Accessible name of the palette and its field. Defaults to \"Search\". */\n 'aria-label'?: string;\n placeholder?: string;\n /** A line under the results, and in place of them when there are none: loading or failed\n * results of a server, a query too short to search. */\n status?: ReactNode;\n /**\n * What the search is narrowed to, such as one resource, shown as a chip before the field.\n * Backspace in the empty field, or the chip's button, calls `onScopeRemove`.\n */\n scope?: string | null;\n onScopeRemove?: () => void;\n className?: string;\n}\n\n/**\n * A command palette: a search field over groups of items to go to or run, in a dialog near the top\n * of the screen. Typing matches the items without case or accents, every word having to match,\n * the best matches first. Arrow keys move through the items, Enter opens one and closes the\n * palette, Escape clears the field, then closes it. A `scope` narrows what it searches, as a chip\n * before the field. It knows no data or router: links go through\n * the app's `RouterProvider`. `useCommandShortcut()` opens it with ⌘K or Ctrl+K.\n */\nexport function CommandPalette({\n isOpen,\n onOpenChange,\n groups,\n inputValue: controlledValue,\n onInputChange,\n 'aria-label': ariaLabel,\n placeholder,\n status,\n scope = null,\n onScopeRemove,\n className,\n}: CommandPaletteProps) {\n const intl = usePanneauIntl();\n const container = usePortalContainer();\n const [uncontrolledValue, setUncontrolledValue] = useState('');\n const value = controlledValue ?? uncontrolledValue;\n const setValue = (next: string) => {\n setUncontrolledValue(next);\n onInputChange?.(next);\n };\n const label = ariaLabel ?? intl.formatMessage(messages.commandPalette);\n const visible = matchCommands(groups, value, intl.locale);\n const count = visible.reduce((total, group) => total + group.items.length, 0);\n\n const changeOpen = (open: boolean) => {\n if (!open) {\n setValue('');\n }\n onOpenChange(open);\n };\n\n if (container === null) {\n return null;\n }\n return (\n <ModalOverlay\n isOpen={isOpen}\n onOpenChange={changeOpen}\n isDismissable\n className={styles.overlay}\n UNSTABLE_portalContainer={container}\n >\n <Modal className={styles.modal}>\n <Dialog\n aria-label={label}\n className={cx('panneau-command-palette', styles.dialog, className)}\n >\n <Autocomplete inputValue={value} onInputChange={setValue}>\n <div className={styles.field}>\n <SearchField\n aria-label={scope !== null ? `${label}: ${scope}` : label}\n autoFocus\n className={styles.search}\n >\n <Icon icon={Search} size=\"md\" className={styles.fieldIcon} />\n {scope !== null ? (\n <span className={styles.scope}>\n <span className={styles.scopeLabel}>{scope}</span>\n <Button\n aria-label={intl.formatMessage(\n messages.commandRemoveScope,\n { scope },\n )}\n className={styles.scopeRemove}\n onPress={onScopeRemove}\n >\n <Icon icon={X} size=\"xs\" />\n </Button>\n </span>\n ) : null}\n <Input\n placeholder={placeholder ?? label}\n className={styles.input}\n onKeyDown={(event) => {\n if (\n event.key === 'Backspace' &&\n value === '' &&\n scope !== null\n ) {\n event.preventDefault();\n onScopeRemove?.();\n }\n }}\n />\n </SearchField>\n {/* Touch screens have no Escape key. */}\n <IconButton\n icon={X}\n label={intl.formatMessage(messages.close)}\n size=\"sm\"\n showTooltip={false}\n className={styles.close}\n onPress={() => changeOpen(false)}\n />\n </div>\n <Menu\n aria-label={label}\n className={styles.list}\n // Without results, the status says why: loading, failed, too short…\n renderEmptyState={() => (\n <p className={styles.empty}>\n {status ??\n intl.formatMessage(messages.commandResults, { count: 0 })}\n </p>\n )}\n >\n {visible.map((group) => (\n <MenuSection key={group.id} id={group.id} className={styles.group}>\n <Header className={styles.groupLabel}>{group.label}</Header>\n {group.items.map((item) => (\n <MenuItem\n key={item.id}\n id={`${group.id}:${item.id}`}\n textValue={item.label}\n href={item.href}\n onAction={() => {\n item.onAction?.();\n if (item.keepsOpen !== true) {\n changeOpen(false);\n }\n }}\n className={styles.item}\n >\n {item.imageUrl !== undefined ? (\n <img\n src={item.imageUrl}\n alt=\"\"\n className={styles.image}\n />\n ) : (\n <span className={styles.icon} aria-hidden=\"true\">\n {item.icon !== undefined ? (\n <Icon icon={item.icon} size=\"md\" />\n ) : null}\n </span>\n )}\n <span className={styles.text}>\n <Text slot=\"label\" className={styles.label}>\n {item.label}\n </Text>\n {item.description !== undefined ? (\n <Text\n slot=\"description\"\n className={styles.description}\n >\n {item.description}\n </Text>\n ) : null}\n </span>\n </MenuItem>\n ))}\n </MenuSection>\n ))}\n </Menu>\n </Autocomplete>\n <div className={styles.footer}>\n <span className={styles.status} role=\"status\">\n {status ?? intl.formatMessage(messages.commandResults, { count })}\n </span>\n <span className={styles.hints} aria-hidden=\"true\">\n <span className={styles.hint}>\n <kbd className={styles.key}>\n <Icon icon={ArrowDownUp} size=\"xs\" />\n </kbd>\n {intl.formatMessage(messages.commandHintMove)}\n </span>\n <span className={styles.hint}>\n <kbd className={styles.key}>\n <Icon icon={CornerDownLeft} size=\"xs\" />\n </kbd>\n {intl.formatMessage(messages.commandHintOpen)}\n </span>\n <span className={styles.hint}>\n <kbd className={styles.key}>esc</kbd>\n {intl.formatMessage(messages.commandHintClose)}\n </span>\n </span>\n </div>\n </Dialog>\n </Modal>\n </ModalOverlay>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import "./CommandPalette.css";
|
|
2
|
+
//#region src/command-palette/CommandPalette.module.css
|
|
3
|
+
var overlay = "panneau-command-palette-overlay";
|
|
4
|
+
var fade = "panneau-command-palette-fade";
|
|
5
|
+
var modal = "panneau-command-palette-modal";
|
|
6
|
+
var rise = "panneau-command-palette-rise";
|
|
7
|
+
var dialog = "panneau-command-palette-dialog";
|
|
8
|
+
var field = "panneau-command-palette-field";
|
|
9
|
+
var search = "panneau-command-palette-search";
|
|
10
|
+
var close = "panneau-command-palette-close";
|
|
11
|
+
var fieldIcon = "panneau-command-palette-field-icon";
|
|
12
|
+
var scope = "panneau-command-palette-scope";
|
|
13
|
+
var scopeLabel = "panneau-command-palette-scope-label";
|
|
14
|
+
var scopeRemove = "panneau-command-palette-scope-remove";
|
|
15
|
+
var input = "panneau-command-palette-input";
|
|
16
|
+
var list = "panneau-command-palette-list";
|
|
17
|
+
var group = "panneau-command-palette-group";
|
|
18
|
+
var groupLabel = "panneau-command-palette-group-label";
|
|
19
|
+
var item = "panneau-command-palette-item";
|
|
20
|
+
var icon = "panneau-command-palette-icon";
|
|
21
|
+
var image = "panneau-command-palette-image";
|
|
22
|
+
var text = "panneau-command-palette-text";
|
|
23
|
+
var label = "panneau-command-palette-label";
|
|
24
|
+
var description = "panneau-command-palette-description";
|
|
25
|
+
var empty = "panneau-command-palette-empty";
|
|
26
|
+
var footer = "panneau-command-palette-footer";
|
|
27
|
+
var hints = "panneau-command-palette-hints";
|
|
28
|
+
var hint = "panneau-command-palette-hint";
|
|
29
|
+
var key = "panneau-command-palette-key";
|
|
30
|
+
var CommandPalette_module_default = {
|
|
31
|
+
overlay,
|
|
32
|
+
fade,
|
|
33
|
+
modal,
|
|
34
|
+
rise,
|
|
35
|
+
dialog,
|
|
36
|
+
field,
|
|
37
|
+
search,
|
|
38
|
+
close,
|
|
39
|
+
fieldIcon,
|
|
40
|
+
scope,
|
|
41
|
+
scopeLabel,
|
|
42
|
+
scopeRemove,
|
|
43
|
+
input,
|
|
44
|
+
list,
|
|
45
|
+
group,
|
|
46
|
+
groupLabel,
|
|
47
|
+
item,
|
|
48
|
+
icon,
|
|
49
|
+
image,
|
|
50
|
+
text,
|
|
51
|
+
label,
|
|
52
|
+
description,
|
|
53
|
+
empty,
|
|
54
|
+
footer,
|
|
55
|
+
hints,
|
|
56
|
+
hint,
|
|
57
|
+
key
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
export { close, CommandPalette_module_default as default, description, dialog, empty, fade, field, fieldIcon, footer, group, groupLabel, hint, hints, icon, image, input, item, key, label, list, modal, overlay, rise, scope, scopeLabel, scopeRemove, search, text };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=CommandPalette.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette.module.js","names":[],"sources":["../../src/command-palette/CommandPalette.module.css"],"sourcesContent":["/* A dialog near the top of the screen: the search field over the results, and a footer with the\n * count and the keys. The whole screen on a phone. */\n\n.overlay {\n position: fixed;\n inset: 0;\n z-index: var(--panneau-z-overlay);\n display: flex;\n align-items: flex-start;\n justify-content: center;\n padding: var(--panneau-command-palette-offset-top, 12dvh) var(--panneau-space-4)\n var(--panneau-space-4);\n background-color: var(--panneau-color-backdrop);\n}\n\n.overlay[data-entering] {\n animation: fade var(--panneau-duration) ease-out;\n}\n\n.modal {\n display: flex;\n width: 100%;\n max-width: var(--panneau-command-palette-width, 40rem);\n outline: none;\n}\n\n.modal[data-entering] {\n animation: rise var(--panneau-duration) ease-out;\n}\n\n.dialog {\n display: flex;\n flex-direction: column;\n width: 100%;\n overflow: hidden;\n color: var(--panneau-color-text);\n background-color: var(--panneau-command-palette-bg, var(--panneau-color-surface-raised));\n border: var(--panneau-border-width) solid var(--panneau-color-border);\n border-radius: var(--panneau-command-palette-radius, var(--panneau-radius-lg));\n box-shadow: var(--panneau-shadow-lg);\n outline: none;\n}\n\n.field {\n display: flex;\n align-items: center;\n gap: var(--panneau-space-2);\n padding: var(--panneau-space-3) var(--panneau-space-4);\n border-bottom: var(--panneau-border-width) solid var(--panneau-color-border);\n}\n\n.search {\n display: flex;\n flex: 1 1 auto;\n align-items: center;\n gap: var(--panneau-space-2);\n min-width: 0;\n}\n\n.close {\n display: none;\n}\n\n.fieldIcon {\n flex: none;\n color: var(--panneau-color-text-muted);\n}\n\n/* What the search is narrowed to, before the field. */\n.scope {\n display: inline-flex;\n flex: none;\n align-items: center;\n gap: var(--panneau-space-1);\n max-width: 50%;\n padding: 0 var(--panneau-space-1) 0 var(--panneau-space-2);\n border-radius: var(--panneau-radius-full);\n background-color: var(--panneau-color-surface-sunken);\n font-size: var(--panneau-font-size-sm);\n font-weight: var(--panneau-font-weight-medium);\n}\n\n.scopeLabel {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.scopeRemove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: var(--panneau-space-1);\n border: 0;\n border-radius: var(--panneau-radius-full);\n background: none;\n color: var(--panneau-color-text-muted);\n cursor: pointer;\n outline: none;\n}\n\n.scopeRemove[data-hovered] {\n color: var(--panneau-color-text);\n}\n\n.scopeRemove[data-focus-visible] {\n outline: var(--panneau-focus-width) solid var(--panneau-color-focus);\n}\n\n.input {\n flex: 1 1 auto;\n min-width: 0;\n padding: var(--panneau-space-1) 0;\n border: 0;\n background: none;\n color: inherit;\n font: inherit;\n font-size: var(--panneau-font-size-lg);\n outline: none;\n}\n\n.input::placeholder {\n color: var(--panneau-color-text-muted);\n}\n\n/* The browser's own clear button: Escape clears the field. */\n.input::-webkit-search-cancel-button {\n appearance: none;\n}\n\n.list {\n display: flex;\n flex-direction: column;\n gap: var(--panneau-space-2);\n max-height: var(--panneau-command-palette-list-max-height, 60dvh);\n padding: var(--panneau-space-2);\n overflow-y: auto;\n outline: none;\n}\n\n.group {\n display: flex;\n flex-direction: column;\n}\n\n.groupLabel {\n padding: var(--panneau-space-1) var(--panneau-space-2);\n color: var(--panneau-color-text-muted);\n font-size: var(--panneau-font-size-xs);\n font-weight: var(--panneau-font-weight-medium);\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--panneau-space-3);\n min-height: var(--panneau-control-height);\n padding: var(--panneau-space-1) var(--panneau-space-2);\n border-radius: var(--panneau-command-palette-item-radius, var(--panneau-radius-md));\n color: var(--panneau-color-text);\n text-decoration: none;\n cursor: pointer;\n outline: none;\n}\n\n.item[data-focused],\n.item[data-hovered] {\n background-color: var(--panneau-command-palette-item-active-bg, var(--panneau-color-hover));\n}\n\n.item[data-focus-visible] {\n box-shadow: inset 0 0 0 var(--panneau-focus-width) var(--panneau-color-focus);\n}\n\n.icon,\n.image {\n display: inline-grid;\n flex: none;\n place-items: center;\n width: 2rem;\n height: 2rem;\n border-radius: var(--panneau-radius-sm);\n color: var(--panneau-color-text-muted);\n background-color: var(--panneau-color-surface-sunken);\n object-fit: cover;\n}\n\n.text {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.label,\n.description {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.description {\n color: var(--panneau-color-text-muted);\n font-size: var(--panneau-font-size-sm);\n}\n\n.empty {\n margin: 0;\n padding: var(--panneau-space-6) var(--panneau-space-2);\n color: var(--panneau-color-text-muted);\n text-align: center;\n}\n\n.footer {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--panneau-space-2);\n padding: var(--panneau-space-2) var(--panneau-space-4);\n border-top: var(--panneau-border-width) solid var(--panneau-color-border);\n color: var(--panneau-color-text-muted);\n font-size: var(--panneau-font-size-xs);\n}\n\n.hints {\n display: flex;\n gap: var(--panneau-space-3);\n}\n\n.hint {\n display: inline-flex;\n align-items: center;\n gap: var(--panneau-space-1);\n}\n\n.key {\n display: inline-grid;\n place-items: center;\n min-width: 1.25rem;\n height: 1.25rem;\n padding: 0 var(--panneau-space-1);\n border: var(--panneau-border-width) solid var(--panneau-color-border);\n border-radius: var(--panneau-radius-sm);\n background: var(--panneau-color-surface);\n font-family: inherit;\n font-size: var(--panneau-font-size-xs);\n}\n\n@keyframes fade {\n from {\n opacity: 0;\n }\n}\n\n@keyframes rise {\n from {\n transform: translateY(-0.5rem);\n opacity: 0;\n }\n}\n\n/* A phone: the whole screen, without the keys, which a touch screen has no use for. */\n@container panneau-root (max-width: 40rem) {\n .overlay {\n padding: 0;\n }\n\n .modal {\n max-width: none;\n height: 100dvh;\n }\n\n .dialog {\n border: 0;\n border-radius: 0;\n }\n\n .list {\n flex: 1 1 auto;\n max-height: none;\n }\n\n .hints {\n display: none;\n }\n\n .close {\n display: inline-flex;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .overlay[data-entering],\n .modal[data-entering] {\n animation: none;\n }\n}\n"],"mappings":""}
|