@raylang/elements 0.7.0 → 0.9.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/base.css +1 -1
- package/components/accordion/accordion.js +7 -4
- package/components/alert/alert.js +2 -1
- package/components/attachment/attachment.js +4 -5
- package/components/blockquote/blockquote.js +2 -2
- package/components/bottom-nav/bottom-nav.js +3 -3
- package/components/carousel/carousel.js +22 -10
- package/components/checkbox/checkbox.js +5 -2
- package/components/checkbox-group/checkbox-group.js +1 -1
- package/components/code/code.js +16 -11
- package/components/color-picker/color-picker.js +5 -5
- package/components/combobox/combobox.js +2 -1
- package/components/command-palette/command-palette.js +17 -2
- package/components/date-picker/date-picker.js +5 -3
- package/components/dialog/dialog.js +1 -1
- package/components/doc-tabs/doc-tabs.js +255 -0
- package/components/drawer/drawer.js +27 -9
- package/components/icon/icon.js +4 -1
- package/components/icon-button/icon-button.js +4 -0
- package/components/indicator/indicator.js +2 -1
- package/components/input/input.js +13 -1
- package/components/menu/menu.js +43 -8
- package/components/mode-input/mode-input.js +221 -0
- package/components/nav-link/nav-link.js +5 -2
- package/components/notification/notification.js +15 -12
- package/components/progress/progress.js +2 -2
- package/components/radio/radio.js +4 -2
- package/components/scroll-area/scroll-area.js +14 -11
- package/components/search/search.js +3 -3
- package/components/segmented-control/segmented-control.js +5 -3
- package/components/select/select.js +3 -3
- package/components/separator/separator.js +8 -3
- package/components/sidebar/sidebar.js +154 -11
- package/components/slider/slider.js +5 -2
- package/components/split/split.js +25 -7
- package/components/stepper/stepper.js +4 -4
- package/components/switch/switch.js +3 -3
- package/components/table/table.js +5 -5
- package/components/tabs/tabs.js +55 -14
- package/components/textarea/textarea.js +13 -1
- package/components/timeline/timeline.js +13 -8
- package/components/toggle-group/toggle-group.js +6 -4
- package/core/complete.js +252 -0
- package/core/core.js +6 -1
- package/core/direction.js +19 -0
- package/core/icons.js +12 -0
- package/core/position.js +11 -3
- package/core/scroll.js +85 -1
- package/core/styles.js +1 -1
- package/core/textlayer.js +214 -0
- package/core.js +1 -0
- package/custom-elements.json +1487 -143
- package/index.js +2 -0
- package/llms-full.txt +224 -28
- package/llms.txt +26 -4
- package/package.json +9 -1
- package/ray-elements.d.ts +190 -31
- package/vscode.html-custom-data.json +477 -22
package/base.css
CHANGED
|
@@ -17,7 +17,7 @@ export class RayAccordion extends RayElement {
|
|
|
17
17
|
value: { type: String },
|
|
18
18
|
multiple: { type: Boolean, reflect: true },
|
|
19
19
|
variant: { type: String, reflect: true, default: "default" },
|
|
20
|
-
chevronPosition: { type: String, reflect: true, default: "
|
|
20
|
+
chevronPosition: { type: String, reflect: true, default: "end" },
|
|
21
21
|
};
|
|
22
22
|
static styles = [accordionStyles];
|
|
23
23
|
static template = `<div class="items" part="items"><slot></slot></div>`;
|
|
@@ -52,7 +52,7 @@ export class RayAccordion extends RayElement {
|
|
|
52
52
|
items.forEach((item, i) => {
|
|
53
53
|
item._setOpen(open.includes(item.value));
|
|
54
54
|
item.dataset.variant = this.variant || "default";
|
|
55
|
-
item.dataset.chevron = this.chevronPosition || "
|
|
55
|
+
item.dataset.chevron = this.chevronPosition || "end";
|
|
56
56
|
item.toggleAttribute("data-first", i === 0);
|
|
57
57
|
item.toggleAttribute("data-last", i === items.length - 1);
|
|
58
58
|
});
|
|
@@ -104,7 +104,7 @@ const itemStyles = css`
|
|
|
104
104
|
font-size: var(--ray-font-size-md);
|
|
105
105
|
font-weight: var(--ray-font-weight-medium);
|
|
106
106
|
color: var(--ray-foreground);
|
|
107
|
-
text-align:
|
|
107
|
+
text-align: start;
|
|
108
108
|
background: transparent;
|
|
109
109
|
border: 0;
|
|
110
110
|
border-radius: inherit;
|
|
@@ -116,7 +116,10 @@ const itemStyles = css`
|
|
|
116
116
|
.label { display: grid; flex: 1; gap: 0.125rem; min-width: 0; }
|
|
117
117
|
.description { font-size: var(--ray-font-size-sm); font-weight: var(--ray-font-weight-normal, 400); color: var(--ray-muted-foreground); }
|
|
118
118
|
.description:empty { display: none; }
|
|
119
|
-
|
|
119
|
+
/* The chevron before the label: start, or left/right as sides of the screen. */
|
|
120
|
+
:host([data-chevron="start"]) .chevron,
|
|
121
|
+
:host([data-chevron="left"]) .chevron:dir(ltr),
|
|
122
|
+
:host([data-chevron="right"]) .chevron:dir(rtl) { order: -1; }
|
|
120
123
|
.chevron { display: inline-flex; color: var(--ray-muted-foreground); transition: transform var(--ray-duration-base) var(--ray-easing-standard); }
|
|
121
124
|
.chevron svg { width: 1rem; height: 1rem; }
|
|
122
125
|
:host([data-open]) .chevron { transform: rotate(180deg); }
|
|
@@ -25,7 +25,7 @@ const styles = css`
|
|
|
25
25
|
width: 16rem;
|
|
26
26
|
max-width: 100%;
|
|
27
27
|
padding: var(--ray-space-2);
|
|
28
|
-
padding-
|
|
28
|
+
padding-inline-end: var(--ray-space-3);
|
|
29
29
|
color: var(--ray-foreground);
|
|
30
30
|
background: var(--ray-card);
|
|
31
31
|
border: 1px solid var(--ray-border);
|
|
@@ -53,7 +53,7 @@ const styles = css`
|
|
|
53
53
|
.badge {
|
|
54
54
|
position: absolute;
|
|
55
55
|
bottom: 3px;
|
|
56
|
-
left: 50%;
|
|
56
|
+
left: 50%; /* physical */
|
|
57
57
|
transform: translateX(-50%);
|
|
58
58
|
padding: 0 0.25rem;
|
|
59
59
|
font-size: 0.5625rem;
|
|
@@ -82,8 +82,7 @@ const styles = css`
|
|
|
82
82
|
:host([status="error"]) .meta { color: var(--ray-destructive); }
|
|
83
83
|
.bar {
|
|
84
84
|
position: absolute;
|
|
85
|
-
|
|
86
|
-
right: 0;
|
|
85
|
+
inset-inline: 0;
|
|
87
86
|
bottom: 0;
|
|
88
87
|
height: 2px;
|
|
89
88
|
background: var(--ray-muted);
|
|
@@ -131,7 +130,7 @@ const styles = css`
|
|
|
131
130
|
:host([variant="card"]) .remove {
|
|
132
131
|
position: absolute;
|
|
133
132
|
top: calc(var(--ray-space-2) + 4px);
|
|
134
|
-
|
|
133
|
+
inset-inline-end: calc(var(--ray-space-2) + 4px);
|
|
135
134
|
background: var(--ray-card);
|
|
136
135
|
box-shadow: var(--ray-shadow-xs);
|
|
137
136
|
opacity: 1;
|
|
@@ -22,7 +22,7 @@ const styles = css`
|
|
|
22
22
|
:host([hide-edge]) { --_edge: 0px; }
|
|
23
23
|
figure { position: relative; margin: 0; }
|
|
24
24
|
/* Room for the mark, so it does not cover what is above or beside. */
|
|
25
|
-
:host([data-icon]) figure { padding: calc(var(--_icon) / 2)
|
|
25
|
+
:host([data-icon]) figure { padding-block-start: calc(var(--_icon) / 2); padding-inline-start: calc(var(--_icon) / 2); }
|
|
26
26
|
blockquote {
|
|
27
27
|
margin: 0;
|
|
28
28
|
padding: var(--_p) calc(var(--_p) * 1.25);
|
|
@@ -43,7 +43,7 @@ const styles = css`
|
|
|
43
43
|
.icon {
|
|
44
44
|
position: absolute;
|
|
45
45
|
top: 0;
|
|
46
|
-
|
|
46
|
+
inset-inline-start: 0;
|
|
47
47
|
display: grid;
|
|
48
48
|
place-items: center;
|
|
49
49
|
width: var(--_icon);
|
|
@@ -40,7 +40,7 @@ const navStyles = css`
|
|
|
40
40
|
grid-auto-columns: minmax(0, 1fr);
|
|
41
41
|
grid-auto-flow: column;
|
|
42
42
|
align-items: stretch;
|
|
43
|
-
padding: var(--ray-space-1) max(var(--ray-space-1), env(safe-area-inset-right, 0px)) max(var(--ray-space-1), env(safe-area-inset-bottom, 0px)) max(var(--ray-space-1), env(safe-area-inset-left, 0px));
|
|
43
|
+
padding: var(--ray-space-1) max(var(--ray-space-1), env(safe-area-inset-right, 0px)) max(var(--ray-space-1), env(safe-area-inset-bottom, 0px)) max(var(--ray-space-1), env(safe-area-inset-left, 0px)); /* physical */
|
|
44
44
|
background: var(--ray-bottom-nav, var(--ray-background));
|
|
45
45
|
border-top: 1px solid var(--ray-border);
|
|
46
46
|
}
|
|
@@ -109,7 +109,7 @@ const itemStyles = css`
|
|
|
109
109
|
.badge {
|
|
110
110
|
position: absolute;
|
|
111
111
|
top: 0;
|
|
112
|
-
|
|
112
|
+
inset-inline-start: calc(50% + 0.375rem);
|
|
113
113
|
min-width: 1rem;
|
|
114
114
|
height: 1rem;
|
|
115
115
|
padding: 0 0.25rem;
|
|
@@ -125,7 +125,7 @@ const itemStyles = css`
|
|
|
125
125
|
box-sizing: content-box;
|
|
126
126
|
}
|
|
127
127
|
.badge:empty:not([data-dot]) { display: none; }
|
|
128
|
-
.badge[data-dot] { min-width: 0; width: 0.5rem; height: 0.5rem; padding: 0; top: 0.25rem;
|
|
128
|
+
.badge[data-dot] { min-width: 0; width: 0.5rem; height: 0.5rem; padding: 0; top: 0.25rem; inset-inline-start: calc(50% + 0.5rem); }
|
|
129
129
|
.label {
|
|
130
130
|
max-width: 100%;
|
|
131
131
|
overflow: hidden;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { RayElement, css, define } from "../../core/core.js";
|
|
11
11
|
import { motionAllowed } from "../../core/motion.js";
|
|
12
|
+
import { isRtl, inlineKey } from "../../core/direction.js";
|
|
12
13
|
|
|
13
14
|
const styles = css`
|
|
14
15
|
:host {
|
|
@@ -74,9 +75,11 @@ const styles = css`
|
|
|
74
75
|
.control:hover:not(:disabled) { background: var(--ray-accent); }
|
|
75
76
|
.control:disabled { opacity: 0; pointer-events: none; }
|
|
76
77
|
.control svg { width: 1rem; height: 1rem; }
|
|
77
|
-
.prev {
|
|
78
|
-
.next {
|
|
79
|
-
:host([orientation="vertical"]) .control { top: auto; left: 50%; transform: translateX(-50%) rotate(90deg); }
|
|
78
|
+
.prev { inset-inline-start: var(--ray-space-2); }
|
|
79
|
+
.next { inset-inline-end: var(--ray-space-2); }
|
|
80
|
+
:host([orientation="vertical"]) .control { top: auto; left: 50%; transform: translateX(-50%) rotate(90deg); } /* physical */
|
|
81
|
+
/* Up and down do not depend on the writing direction: the turned arrows are not mirrored. */
|
|
82
|
+
:host([orientation="vertical"]) .control [data-ray-icon] > svg { transform: none; }
|
|
80
83
|
:host([orientation="vertical"]) .prev { top: var(--ray-space-2); }
|
|
81
84
|
:host([orientation="vertical"]) .next { bottom: var(--ray-space-2); }
|
|
82
85
|
:host([hide-controls]) .control { display: none; }
|
|
@@ -272,6 +275,14 @@ export class RayCarousel extends RayElement {
|
|
|
272
275
|
return this.orientation === "vertical";
|
|
273
276
|
}
|
|
274
277
|
|
|
278
|
+
// The scroll offset from the start. Right to left, scrollLeft runs from 0
|
|
279
|
+
// (the start, on the right) down to negative values.
|
|
280
|
+
_scroll() {
|
|
281
|
+
const vp = this.viewport;
|
|
282
|
+
if (this._vertical()) return vp.scrollTop;
|
|
283
|
+
return isRtl(this) ? -vp.scrollLeft : vp.scrollLeft;
|
|
284
|
+
}
|
|
285
|
+
|
|
275
286
|
_current() {
|
|
276
287
|
return Math.min(Math.max(0, this.index ?? 0), this.count - 1);
|
|
277
288
|
}
|
|
@@ -294,11 +305,12 @@ export class RayCarousel extends RayElement {
|
|
|
294
305
|
const vr = vp.getBoundingClientRect();
|
|
295
306
|
const size = v ? vp.clientHeight : vp.clientWidth;
|
|
296
307
|
const max = Math.max(0, v ? vp.scrollHeight - vp.clientHeight : vp.scrollWidth - vp.clientWidth);
|
|
297
|
-
const scroll =
|
|
308
|
+
const scroll = this._scroll();
|
|
309
|
+
const rtl = !v && isRtl(this);
|
|
298
310
|
const snaps = [];
|
|
299
311
|
for (const s of slides) {
|
|
300
312
|
const r = s.getBoundingClientRect();
|
|
301
|
-
const start = (v ? r.top - vr.top : r.left - vr.left) + scroll;
|
|
313
|
+
const start = (v ? r.top - vr.top : rtl ? vr.right - r.right : r.left - vr.left) + scroll;
|
|
302
314
|
const length = v ? r.height : r.width;
|
|
303
315
|
const pos = this.align === "center" ? start - (size - length) / 2 : start;
|
|
304
316
|
const clamped = Math.round(Math.min(max, Math.max(0, pos)));
|
|
@@ -333,8 +345,7 @@ export class RayCarousel extends RayElement {
|
|
|
333
345
|
|
|
334
346
|
// The position closest to the current scroll offset.
|
|
335
347
|
_track() {
|
|
336
|
-
const
|
|
337
|
-
const scroll = this._vertical() ? vp.scrollTop : vp.scrollLeft;
|
|
348
|
+
const scroll = this._scroll();
|
|
338
349
|
let best = 0;
|
|
339
350
|
for (let i = 1; i < this.#snaps.length; i++) {
|
|
340
351
|
if (Math.abs(this.#snaps[i] - scroll) < Math.abs(this.#snaps[best] - scroll)) best = i;
|
|
@@ -358,7 +369,7 @@ export class RayCarousel extends RayElement {
|
|
|
358
369
|
const smooth = user && !instant && !reduced?.matches && motionAllowed(this);
|
|
359
370
|
const opts = { behavior: smooth ? "smooth" : "instant" };
|
|
360
371
|
if (this._vertical()) this.viewport.scrollTo({ top: pos, ...opts });
|
|
361
|
-
else this.viewport.scrollTo({ left: pos, ...opts });
|
|
372
|
+
else this.viewport.scrollTo({ left: isRtl(this) ? -pos : pos, ...opts });
|
|
362
373
|
this._setIndex(i);
|
|
363
374
|
this._paint();
|
|
364
375
|
this._schedule();
|
|
@@ -416,10 +427,11 @@ export class RayCarousel extends RayElement {
|
|
|
416
427
|
const v = this._vertical();
|
|
417
428
|
const back = v ? "ArrowUp" : "ArrowLeft";
|
|
418
429
|
const fwd = v ? "ArrowDown" : "ArrowRight";
|
|
419
|
-
|
|
430
|
+
const key = v ? e.key : inlineKey(e.key, this);
|
|
431
|
+
if (key === fwd) {
|
|
420
432
|
e.preventDefault();
|
|
421
433
|
this.next();
|
|
422
|
-
} else if (
|
|
434
|
+
} else if (key === back) {
|
|
423
435
|
e.preventDefault();
|
|
424
436
|
this.prev();
|
|
425
437
|
} else if (e.key === "Home") {
|
|
@@ -19,7 +19,10 @@ export const checkStyles = css`
|
|
|
19
19
|
align-items: flex-start;
|
|
20
20
|
gap: calc(var(--_s) * 0.6);
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
/* The label before the box: start, or left/right as sides of the screen. */
|
|
23
|
+
:host([label-position="start"]) .root,
|
|
24
|
+
:host([label-position="left"]) .root:dir(ltr),
|
|
25
|
+
:host([label-position="right"]) .root:dir(rtl) { flex-direction: row-reverse; justify-content: flex-end; }
|
|
23
26
|
.inner {
|
|
24
27
|
position: relative;
|
|
25
28
|
flex: none;
|
|
@@ -100,7 +103,7 @@ export class RayCheckbox extends FieldControl {
|
|
|
100
103
|
value: { type: String, reflect: true, default: "on" },
|
|
101
104
|
color: { type: String, reflect: true },
|
|
102
105
|
variant: { type: String, reflect: true, default: "filled" },
|
|
103
|
-
labelPosition: { type: String, reflect: true, default: "
|
|
106
|
+
labelPosition: { type: String, reflect: true, default: "end" },
|
|
104
107
|
};
|
|
105
108
|
static styles = [sizeStyles, radiusStyles, fieldStyles, checkStyles, styles];
|
|
106
109
|
static template = checkTemplate(`<span class="indicator" part="indicator" aria-hidden="true"><span class="check" data-ray-icon="ui.checked"></span><span class="dash" data-ray-icon="ui.indeterminate"></span></span>`);
|
|
@@ -15,7 +15,7 @@ const styles = css`
|
|
|
15
15
|
.items { display: flex; flex-direction: column; gap: var(--ray-space-3); margin-top: var(--ray-space-2); }
|
|
16
16
|
:host([orientation="horizontal"]) .items { flex-direction: row; flex-wrap: wrap; gap: var(--ray-space-3) var(--ray-space-5); }
|
|
17
17
|
.label { margin-bottom: 0; }
|
|
18
|
-
.count { margin-
|
|
18
|
+
.count { margin-inline-start: var(--ray-space-1); font-weight: 400; color: var(--ray-muted-foreground); font-variant-numeric: tabular-nums; }
|
|
19
19
|
`;
|
|
20
20
|
|
|
21
21
|
/** "a, b" (an attribute) or an array, as an array of values. */
|
package/components/code/code.js
CHANGED
|
@@ -293,7 +293,8 @@ const styles = css`
|
|
|
293
293
|
align-items: center;
|
|
294
294
|
gap: var(--ray-space-2);
|
|
295
295
|
min-height: 2.5rem;
|
|
296
|
-
padding: 0
|
|
296
|
+
padding-block: 0;
|
|
297
|
+
padding-inline: var(--ray-space-4) var(--ray-space-2);
|
|
297
298
|
font-size: var(--ray-font-size-xs);
|
|
298
299
|
color: var(--ray-muted-foreground);
|
|
299
300
|
border-bottom: 1px solid var(--ray-border);
|
|
@@ -325,12 +326,13 @@ const styles = css`
|
|
|
325
326
|
.copy-label { display: none; }
|
|
326
327
|
.copy[data-copied] .copy-label { display: inline; }
|
|
327
328
|
/* Without a header, the button floats in the top-end corner. */
|
|
328
|
-
.copy.floating { position: absolute; z-index: 1; top: var(--ray-space-2);
|
|
329
|
+
.copy.floating { position: absolute; z-index: 1; top: var(--ray-space-2); inset-inline-end: var(--ray-space-2); background: var(--ray-code-background); opacity: 0; transition: opacity var(--ray-duration-fast); }
|
|
329
330
|
.frame:hover .copy.floating, .copy.floating:focus-visible, .copy.floating[data-copied] { opacity: 1; }
|
|
330
331
|
@media (hover: none) { .copy.floating { opacity: 1; } }
|
|
331
332
|
.copy[hidden] { display: none; }
|
|
332
333
|
|
|
333
|
-
|
|
334
|
+
/* Code reads left to right, in a right-to-left page too. */
|
|
335
|
+
.scroller { direction: ltr; overflow: auto; max-height: var(--_max, none); outline: none; }
|
|
334
336
|
.scroller:focus-visible { box-shadow: inset 0 0 0 2px var(--ray-ring); }
|
|
335
337
|
:host([expanded]) .scroller { max-height: none; }
|
|
336
338
|
pre { margin: 0; padding: var(--ray-space-3) 0; font-family: var(--ray-font-mono); font-size: var(--_fs); line-height: var(--_lh); tab-size: 2; }
|
|
@@ -339,19 +341,19 @@ const styles = css`
|
|
|
339
341
|
.line { display: block; padding: 0 var(--ray-space-4); white-space: pre; border-inline-start: 2px solid transparent; }
|
|
340
342
|
:host([wrap]) .line { white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
341
343
|
.line:empty::after { content: " "; }
|
|
342
|
-
:host([line-numbers]) .line { counter-increment: line; padding-
|
|
344
|
+
:host([line-numbers]) .line { counter-increment: line; padding-inline-start: 0; }
|
|
343
345
|
:host([line-numbers]) .line::before {
|
|
344
346
|
content: counter(line);
|
|
345
347
|
display: inline-block;
|
|
346
348
|
width: calc(var(--_digits, 2) * 1ch + var(--ray-space-6));
|
|
347
349
|
padding-inline-end: var(--ray-space-4);
|
|
348
350
|
box-sizing: border-box;
|
|
349
|
-
text-align:
|
|
351
|
+
text-align: end;
|
|
350
352
|
color: var(--ray-code-comment);
|
|
351
353
|
opacity: 0.7;
|
|
352
354
|
user-select: none;
|
|
353
355
|
}
|
|
354
|
-
:host([line-numbers][wrap]) .line { padding-
|
|
356
|
+
:host([line-numbers][wrap]) .line { padding-inline-start: calc(var(--_digits, 2) * 1ch + var(--ray-space-6)); text-indent: calc((var(--_digits, 2) * 1ch + var(--ray-space-6)) * -1); }
|
|
355
357
|
.line[data-highlight] { background: color-mix(in srgb, var(--ray-primary) 12%, transparent); border-inline-start-color: var(--ray-primary); }
|
|
356
358
|
.line[data-diff="add"] { color: var(--ray-code-added); background: color-mix(in srgb, var(--ray-code-added) 12%, transparent); }
|
|
357
359
|
.line[data-diff="remove"] { color: var(--ray-code-removed); background: color-mix(in srgb, var(--ray-code-removed) 12%, transparent); }
|
|
@@ -398,6 +400,7 @@ export class RayCode extends RayElement {
|
|
|
398
400
|
lineNumbers: { type: Boolean, reflect: true },
|
|
399
401
|
highlight: { type: String },
|
|
400
402
|
wrap: { type: Boolean, reflect: true },
|
|
403
|
+
verbatim: { type: Boolean, reflect: true },
|
|
401
404
|
maxHeight: { type: String },
|
|
402
405
|
expanded: { type: Boolean, reflect: true },
|
|
403
406
|
hideCopy: { type: Boolean, reflect: true },
|
|
@@ -448,20 +451,22 @@ export class RayCode extends RayElement {
|
|
|
448
451
|
this.#observer.disconnect();
|
|
449
452
|
}
|
|
450
453
|
|
|
451
|
-
/** The code shown (dedented), whatever its source. */
|
|
454
|
+
/** The code shown (dedented unless verbatim), whatever its source. */
|
|
452
455
|
get source() {
|
|
453
456
|
return this.#source;
|
|
454
457
|
}
|
|
455
458
|
|
|
456
459
|
#readSource() {
|
|
457
|
-
|
|
460
|
+
// verbatim: data (a response body, a log) is shown and copied as it came.
|
|
461
|
+
const shape = this.verbatim ? String : dedent;
|
|
462
|
+
if (typeof this.code === "string") return shape(this.code);
|
|
458
463
|
// A <template> is parsed as HTML: perfect for markup; its serialization
|
|
459
464
|
// escapes &, < and > in text, undone here.
|
|
460
465
|
const tpl = this.querySelector(":scope > template");
|
|
461
|
-
if (tpl) return
|
|
466
|
+
if (tpl) return shape(tpl.innerHTML.replace(/</g, "<").replace(/>/g, ">").replace(/ /g, "\u00a0").replace(/&/g, "&"));
|
|
462
467
|
const script = this.querySelector(':scope > script[type="text/plain"]');
|
|
463
|
-
if (script) return
|
|
464
|
-
return
|
|
468
|
+
if (script) return shape(script.textContent);
|
|
469
|
+
return shape(this.textContent);
|
|
465
470
|
}
|
|
466
471
|
|
|
467
472
|
update() {
|
|
@@ -172,7 +172,7 @@ const pickerStyles = css`
|
|
|
172
172
|
height: calc(var(--_w) * 0.62);
|
|
173
173
|
background:
|
|
174
174
|
linear-gradient(to top, #000, transparent),
|
|
175
|
-
linear-gradient(to right, #fff, hsl(var(--_hue) 100% 50%));
|
|
175
|
+
linear-gradient(to right, #fff, hsl(var(--_hue) 100% 50%)); /* physical */
|
|
176
176
|
border-radius: var(--ray-radius-sm);
|
|
177
177
|
cursor: crosshair;
|
|
178
178
|
touch-action: none;
|
|
@@ -180,7 +180,7 @@ const pickerStyles = css`
|
|
|
180
180
|
:host([full-width]) .area { height: auto; aspect-ratio: 5 / 3; }
|
|
181
181
|
.area-thumb {
|
|
182
182
|
position: absolute;
|
|
183
|
-
left: var(--_s);
|
|
183
|
+
left: var(--_s); /* physical */
|
|
184
184
|
top: calc(100% - var(--_v));
|
|
185
185
|
width: var(--_thumb);
|
|
186
186
|
height: var(--_thumb);
|
|
@@ -209,13 +209,13 @@ const pickerStyles = css`
|
|
|
209
209
|
inset: 0 calc(var(--_thumb) / -2);
|
|
210
210
|
border-radius: inherit;
|
|
211
211
|
}
|
|
212
|
-
.hue::before { background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00); }
|
|
213
|
-
.alpha::before { background: linear-gradient(to right, transparent, var(--_solid)), ${CHECKER}; }
|
|
212
|
+
.hue::before { background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00); } /* physical */
|
|
213
|
+
.alpha::before { background: linear-gradient(to right, transparent, var(--_solid)), ${CHECKER}; } /* physical */
|
|
214
214
|
:host(:not([data-alpha])) .alpha { display: none; }
|
|
215
215
|
.slider-thumb {
|
|
216
216
|
position: absolute;
|
|
217
217
|
top: 50%;
|
|
218
|
-
left: var(--_pos);
|
|
218
|
+
left: var(--_pos); /* physical */
|
|
219
219
|
width: var(--_thumb);
|
|
220
220
|
height: var(--_thumb);
|
|
221
221
|
box-sizing: border-box;
|
|
@@ -30,7 +30,8 @@ const styles = css`
|
|
|
30
30
|
max-width: 100%;
|
|
31
31
|
height: calc(var(--_h) - 0.75rem);
|
|
32
32
|
min-height: 1.375rem;
|
|
33
|
-
padding: 0
|
|
33
|
+
padding-block: 0;
|
|
34
|
+
padding-inline: 0.5rem 0.125rem;
|
|
34
35
|
font-size: calc(var(--_fs) - 0.0625rem);
|
|
35
36
|
color: var(--ray-foreground);
|
|
36
37
|
background: var(--ray-muted);
|
|
@@ -86,6 +86,7 @@ const styles = css`
|
|
|
86
86
|
.icon { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 1.25rem; height: 1.25rem; color: var(--ray-muted-foreground); }
|
|
87
87
|
.option[aria-selected="true"] .icon { color: inherit; }
|
|
88
88
|
.icon svg { width: 1rem; height: 1rem; }
|
|
89
|
+
.prefix { flex: none; display: inline-flex; align-items: center; font-size: var(--ray-font-size-xs); color: var(--ray-muted-foreground); }
|
|
89
90
|
.text { display: flex; flex: 1; flex-direction: column; min-width: 0; }
|
|
90
91
|
.label, .description { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
91
92
|
.label { font-size: var(--ray-font-size-sm); }
|
|
@@ -110,7 +111,7 @@ const styles = css`
|
|
|
110
111
|
.hint b {
|
|
111
112
|
display: inline-block;
|
|
112
113
|
min-width: 1.25rem;
|
|
113
|
-
margin-
|
|
114
|
+
margin-inline-end: var(--ray-space-1);
|
|
114
115
|
padding: 0 0.3rem;
|
|
115
116
|
font-family: var(--ray-font-mono);
|
|
116
117
|
font-size: 0.6875rem;
|
|
@@ -187,6 +188,9 @@ export class RayCommandPalette extends RayElement {
|
|
|
187
188
|
emptyLabel: { type: String, default: "Nothing found" },
|
|
188
189
|
label: { type: String, default: "Command palette" },
|
|
189
190
|
hideHint: { type: Boolean, reflect: true },
|
|
191
|
+
navigateLabel: { type: String, default: "navigate" },
|
|
192
|
+
runLabel: { type: String, default: "run" },
|
|
193
|
+
closeLabel: { type: String, default: "close" },
|
|
190
194
|
overlayBlur: { type: String },
|
|
191
195
|
nativeMenus: { type: Boolean, attribute: "native-menus", reflect: true },
|
|
192
196
|
};
|
|
@@ -196,7 +200,7 @@ export class RayCommandPalette extends RayElement {
|
|
|
196
200
|
<div class="search" part="search">${SEARCH_ICON}<input id="input" part="input" role="combobox" aria-expanded="true" aria-controls="list" aria-autocomplete="list" autocomplete="off" spellcheck="false"></div>
|
|
197
201
|
<div class="list" id="list" role="listbox" part="list"></div>
|
|
198
202
|
<div class="empty" part="empty" hidden></div>
|
|
199
|
-
<div class="hint" part="hint"><span><b>↑↓</b> navigate
|
|
203
|
+
<div class="hint" part="hint"><span><b>↑↓</b> <span id="hint-navigate"></span></span><span><b>↵</b> <span id="hint-run"></span></span><span><b>esc</b> <span id="hint-close"></span></span></div>
|
|
200
204
|
<slot name="overlay"></slot>
|
|
201
205
|
</dialog>`;
|
|
202
206
|
|
|
@@ -281,6 +285,9 @@ export class RayCommandPalette extends RayElement {
|
|
|
281
285
|
this.dialog.setAttribute("aria-label", this.label ?? "Command palette");
|
|
282
286
|
if (this.input.value !== (this.query ?? "")) this.input.value = this.query ?? "";
|
|
283
287
|
this.$(".hint").hidden = Boolean(this.hideHint);
|
|
288
|
+
this.$("#hint-navigate").textContent = this.navigateLabel ?? "";
|
|
289
|
+
this.$("#hint-run").textContent = this.runLabel ?? "";
|
|
290
|
+
this.$("#hint-close").textContent = this.closeLabel ?? "";
|
|
284
291
|
this._render();
|
|
285
292
|
if (changed.has("open") || this._first === undefined) {
|
|
286
293
|
this._first = false;
|
|
@@ -399,6 +406,14 @@ export class RayCommandPalette extends RayElement {
|
|
|
399
406
|
else icon.textContent = String(a.icon);
|
|
400
407
|
opt.append(icon);
|
|
401
408
|
}
|
|
409
|
+
// Content of its own before the text, any width: a colored method tag.
|
|
410
|
+
if (a.prefix !== undefined && a.prefix !== null && a.prefix !== "") {
|
|
411
|
+
const prefix = document.createElement("span");
|
|
412
|
+
prefix.className = "prefix";
|
|
413
|
+
if (a.prefix instanceof Node) prefix.append(a.prefix);
|
|
414
|
+
else prefix.textContent = String(a.prefix);
|
|
415
|
+
opt.append(prefix);
|
|
416
|
+
}
|
|
402
417
|
const text = document.createElement("span");
|
|
403
418
|
text.className = "text";
|
|
404
419
|
const label = document.createElement("span");
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// arithmetic), so no time zone shifts a day.
|
|
13
13
|
|
|
14
14
|
import { RayElement, css, define } from "../../core/core.js";
|
|
15
|
+
import { inlineKey } from "../../core/direction.js";
|
|
15
16
|
import { sizeStyles, radiusStyles } from "../../core/styles.js";
|
|
16
17
|
import { place, autoUpdate } from "../../core/position.js";
|
|
17
18
|
import { dismissable } from "../../core/dismiss.js";
|
|
@@ -268,7 +269,8 @@ export class RayCalendar extends RayElement {
|
|
|
268
269
|
const d = this._focusDate();
|
|
269
270
|
const first = this.firstDay ?? firstDayOf(localeOf(this));
|
|
270
271
|
let next = null;
|
|
271
|
-
|
|
272
|
+
// The grid follows the writing direction: right to left, ArrowLeft is the next day.
|
|
273
|
+
switch (inlineKey(e.key, this)) {
|
|
272
274
|
case "ArrowLeft": next = addDays(d, -1); break;
|
|
273
275
|
case "ArrowRight": next = addDays(d, 1); break;
|
|
274
276
|
case "ArrowUp": next = addDays(d, -7); break;
|
|
@@ -321,7 +323,7 @@ const pickerStyles = css`
|
|
|
321
323
|
gap: var(--ray-space-2);
|
|
322
324
|
width: 100%;
|
|
323
325
|
min-width: 0;
|
|
324
|
-
text-align:
|
|
326
|
+
text-align: start;
|
|
325
327
|
color: inherit;
|
|
326
328
|
background: transparent;
|
|
327
329
|
border: 0;
|
|
@@ -340,7 +342,7 @@ const pickerStyles = css`
|
|
|
340
342
|
justify-content: center;
|
|
341
343
|
width: calc(var(--_h) * 0.6);
|
|
342
344
|
height: calc(var(--_h) * 0.6);
|
|
343
|
-
margin-
|
|
345
|
+
margin-inline-end: calc(var(--_px) * 0.4);
|
|
344
346
|
padding: 0;
|
|
345
347
|
color: var(--ray-muted-foreground);
|
|
346
348
|
background: transparent;
|
|
@@ -66,7 +66,7 @@ const styles = css`
|
|
|
66
66
|
justify-content: center;
|
|
67
67
|
width: var(--ray-control-height-xs);
|
|
68
68
|
height: var(--ray-control-height-xs);
|
|
69
|
-
margin-
|
|
69
|
+
margin-inline-start: auto;
|
|
70
70
|
padding: 0;
|
|
71
71
|
color: var(--ray-muted-foreground);
|
|
72
72
|
background: transparent;
|