@raylang/elements 0.6.0 → 0.8.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/check/check.d.ts +2 -0
- package/check/check.js +18 -4
- package/check/cli.js +10 -6
- package/components/accordion/accordion.js +8 -5
- package/components/alert/alert.js +3 -2
- package/components/attachment/attachment.js +5 -6
- package/components/avatar/avatar.js +1 -1
- package/components/blockquote/blockquote.js +2 -2
- package/components/bottom-nav/bottom-nav.js +5 -3
- package/components/breadcrumbs/breadcrumbs.js +1 -1
- package/components/carousel/carousel.js +26 -14
- package/components/checkbox/checkbox.js +6 -3
- package/components/checkbox-group/checkbox-group.js +1 -1
- package/components/code/code.js +9 -7
- package/components/color-picker/color-picker.js +6 -6
- package/components/combobox/combobox.js +5 -4
- package/components/command-palette/command-palette.js +2 -2
- package/components/date-picker/date-picker.js +9 -7
- package/components/dialog/dialog.js +2 -2
- package/components/drawer/drawer.js +28 -10
- package/components/file-upload/file-upload.js +1 -1
- package/components/icon/icon.js +9 -1
- package/components/indicator/indicator.js +2 -1
- package/components/menu/menu.js +1 -1
- package/components/nav-link/nav-link.js +6 -3
- package/components/notification/notification.js +16 -13
- package/components/number-input/number-input.js +1 -1
- package/components/pagination/pagination.js +4 -4
- package/components/password-input/password-input.js +2 -2
- 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 +5 -5
- package/components/segmented-control/segmented-control.js +5 -3
- package/components/select/select.js +5 -5
- package/components/separator/separator.js +8 -3
- package/components/sidebar/sidebar.js +14 -6
- package/components/slider/slider.js +5 -2
- package/components/split/split.js +12 -6
- package/components/stat/stat.js +1 -1
- package/components/step-dots/step-dots.js +11 -2
- package/components/stepper/stepper.js +5 -5
- package/components/switch/switch.js +3 -3
- package/components/table/table.js +6 -6
- package/components/tabs/tabs.js +11 -8
- package/components/theme-toggle/theme-toggle.js +2 -2
- package/components/timeline/timeline.js +13 -8
- package/components/toggle-group/toggle-group.js +6 -4
- package/core/core.js +10 -4
- package/core/direction.js +19 -0
- package/core/icons.js +107 -8
- package/core/position.js +11 -3
- package/core/styles.js +1 -1
- package/core.js +1 -0
- package/custom-elements.json +151 -79
- package/llms-full.txt +75 -31
- package/llms.txt +32 -3
- package/package.json +1 -1
- package/ray-elements.d.ts +56 -39
- package/vscode.html-custom-data.json +1102 -39
package/core/icons.js
CHANGED
|
@@ -6,6 +6,20 @@
|
|
|
6
6
|
//
|
|
7
7
|
// setIcons() also adds new names, for <ray-icon name="…">. Icons are SVG
|
|
8
8
|
// markup (or an SVGElement) drawn with currentColor; components size them.
|
|
9
|
+
//
|
|
10
|
+
// The components ask for roles, not glyphs: "ui.close" (a dialog's close
|
|
11
|
+
// button), "ui.remove" (a chip's ×), "ui.clear" (a field's ×)… Each role
|
|
12
|
+
// draws its glyph (ALIASES) unless the app registers the role itself, so
|
|
13
|
+
// setIcons({ close: … }) still changes every × and setIcons({ "ui.remove": … })
|
|
14
|
+
// only the chips'.
|
|
15
|
+
//
|
|
16
|
+
// The roles that point along the text (ui.next, ui.previous, ui.disclosure…;
|
|
17
|
+
// MIRRORED) are drawn mirrored in a right-to-left context, the glyph or the
|
|
18
|
+
// app's own icon alike: the next page is to the left there.
|
|
19
|
+
//
|
|
20
|
+
// An icon may have a filled version, "<name>:filled", for a state: the active
|
|
21
|
+
// tab, a favorite, unread. <ray-icon name="star" filled> draws it, and the
|
|
22
|
+
// outline one when there is none. setIcons({ "star:filled": … }) adds one.
|
|
9
23
|
// The markup is inserted as HTML: register icons from your own code only,
|
|
10
24
|
// never from user input.
|
|
11
25
|
|
|
@@ -62,12 +76,80 @@ const DEFAULTS = {
|
|
|
62
76
|
"message-circle": svg(`<path d="M20 11.5a8 8 0 0 1-11.6 7.2L4 20l1.3-4.2A8 8 0 1 1 20 11.5z"/>`),
|
|
63
77
|
};
|
|
64
78
|
|
|
65
|
-
|
|
79
|
+
// The filled versions: the outline's shapes filled (same silhouette: the
|
|
80
|
+
// stroke stays), or one even-odd path where a mark is cut out of a disc.
|
|
81
|
+
const solid = (body) =>
|
|
82
|
+
`<svg viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${body}</svg>`;
|
|
83
|
+
const cut = (d) => `<svg viewBox="0 0 24 24" fill="currentColor" fill-rule="evenodd" aria-hidden="true"><path d="${d}"/></svg>`;
|
|
84
|
+
|
|
85
|
+
/** The filled versions of the default set (registered as "<name>:filled"). */
|
|
86
|
+
const FILLED = {
|
|
87
|
+
"user": solid(`<circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0z"/>`),
|
|
88
|
+
"info": cut("M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm1 15h-2v-6h2zm0-8h-2V7h2z"),
|
|
89
|
+
"circle-check": cut("M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm-1.5 14.5-4-4 1.4-1.4 2.6 2.6 5.6-5.6 1.4 1.4z"),
|
|
90
|
+
"alert-triangle": cut("M10.3 3.2 1.6 18.1a2 2 0 0 0 1.7 3h17.4a2 2 0 0 0 1.7-3L13.7 3.2a2 2 0 0 0-3.4 0zM11 8.5h2v5.5h-2zM12 16a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5z"),
|
|
91
|
+
"circle-x": cut("M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zM14.12 8.46 15.54 9.88 13.41 12 15.54 14.12 14.12 15.54 12 13.41 9.88 15.54 8.46 14.12 10.59 12 8.46 9.88 9.88 8.46 12 10.59z"),
|
|
92
|
+
"folder": solid(`<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>`),
|
|
93
|
+
bell: solid(`<path d="M10.3 21a1.9 1.9 0 0 0 3.4 0z"/><path d="M3.3 15.3A1 1 0 0 0 4 17h16a1 1 0 0 0 .7-1.7C19.4 14 18 12.6 18 8A6 6 0 0 0 6 8c0 4.6-1.4 6-2.7 7.3"/>`),
|
|
94
|
+
"star": solid(`<path d="M12 3.5l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.9l-5.2 2.7 1-5.8-4.3-4.1 5.9-.9z"/>`),
|
|
95
|
+
"settings": solid(`<path d="M4 6h10M18 6h2M4 12h4M12 12h8M4 18h12"/><circle cx="16" cy="6" r="2"/><circle cx="10" cy="12" r="2"/><circle cx="18" cy="18" r="2"/>`),
|
|
96
|
+
"home": solid(`<path d="M4 10.5 12 4l8 6.5V19a1 1 0 0 1-1 1h-4.5v-5.5h-5V20H5a1 1 0 0 1-1-1z"/>`),
|
|
97
|
+
"message-circle": solid(`<path d="M20 11.5a8 8 0 0 1-11.6 7.2L4 20l1.3-4.2A8 8 0 1 1 20 11.5z"/>`),
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const FILLED_SUFFIX = ":filled";
|
|
101
|
+
|
|
102
|
+
/** The roles the components draw, and the glyph each one uses by default. */
|
|
103
|
+
const ALIASES = {
|
|
104
|
+
"ui.close": "close",
|
|
105
|
+
"ui.clear": "close",
|
|
106
|
+
"ui.remove": "close",
|
|
107
|
+
"ui.expand": "chevron-down",
|
|
108
|
+
"ui.disclosure": "chevron-right",
|
|
109
|
+
"ui.previous": "chevron-left",
|
|
110
|
+
"ui.next": "chevron-right",
|
|
111
|
+
"ui.first": "chevrons-left",
|
|
112
|
+
"ui.last": "chevrons-right",
|
|
113
|
+
"ui.separator": "chevron-right",
|
|
114
|
+
"ui.increment": "chevron-up",
|
|
115
|
+
"ui.decrement": "chevron-down",
|
|
116
|
+
"ui.sort": "chevron-up",
|
|
117
|
+
"ui.checked": "check",
|
|
118
|
+
"ui.indeterminate": "minus",
|
|
119
|
+
"ui.copy": "copy",
|
|
120
|
+
"ui.copied": "check",
|
|
121
|
+
"ui.show-password": "eye",
|
|
122
|
+
"ui.hide-password": "eye-off",
|
|
123
|
+
"ui.play": "play",
|
|
124
|
+
"ui.pause": "pause",
|
|
125
|
+
"ui.search": "search",
|
|
126
|
+
"ui.calendar": "calendar",
|
|
127
|
+
"ui.eyedropper": "pipette",
|
|
128
|
+
"ui.upload": "upload",
|
|
129
|
+
"ui.avatar": "user",
|
|
130
|
+
"ui.theme-light": "sun",
|
|
131
|
+
"ui.theme-dark": "moon",
|
|
132
|
+
"ui.theme-system": "monitor",
|
|
133
|
+
"ui.trend-up": "arrow-up-right",
|
|
134
|
+
"ui.trend-down": "arrow-down-right",
|
|
135
|
+
"ui.trend-flat": "minus",
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/** The roles that point along the text: mirrored in a right-to-left context. */
|
|
139
|
+
const MIRRORED = new Set(["ui.disclosure", "ui.previous", "ui.next", "ui.first", "ui.last", "ui.separator"]);
|
|
140
|
+
|
|
141
|
+
/** Whether an icon is drawn mirrored right to left (a role that points along the text). */
|
|
142
|
+
export function mirrorsInRtl(name) {
|
|
143
|
+
return MIRRORED.has(name);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const registry = new Map([...Object.entries(DEFAULTS), ...Object.entries(FILLED).map(([name, markup]) => [name + FILLED_SUFFIX, markup])]);
|
|
66
147
|
const listeners = new Set();
|
|
67
148
|
const warned = new Set();
|
|
68
149
|
|
|
69
150
|
/**
|
|
70
|
-
* Replaces or adds icons. Values are SVG markup or an SVGElement
|
|
151
|
+
* Replaces or adds icons. Values are SVG markup or an SVGElement; a name
|
|
152
|
+
* ending in ":filled" is the filled version of an icon.
|
|
71
153
|
* @param {Record<string, string | SVGElement>} icons
|
|
72
154
|
*/
|
|
73
155
|
export function setIcons(icons) {
|
|
@@ -81,9 +163,19 @@ export function setIcons(icons) {
|
|
|
81
163
|
for (const cb of listeners) cb();
|
|
82
164
|
}
|
|
83
165
|
|
|
84
|
-
/**
|
|
85
|
-
|
|
86
|
-
|
|
166
|
+
/**
|
|
167
|
+
* The SVG markup of an icon or a role ("" and one warning when it is not
|
|
168
|
+
* registered). With `filled`, its filled version, or the outline one when it
|
|
169
|
+
* has none.
|
|
170
|
+
*/
|
|
171
|
+
export function getIcon(name, { filled = false } = {}) {
|
|
172
|
+
// A role the app has not registered draws its glyph.
|
|
173
|
+
const glyph = ALIASES[name];
|
|
174
|
+
if (filled) {
|
|
175
|
+
const solidMarkup = registry.get(name + FILLED_SUFFIX) ?? (glyph && !registry.has(name) ? registry.get(glyph + FILLED_SUFFIX) : undefined);
|
|
176
|
+
if (solidMarkup !== undefined) return solidMarkup;
|
|
177
|
+
}
|
|
178
|
+
const markup = registry.get(name) ?? (glyph ? registry.get(glyph) : undefined);
|
|
87
179
|
if (markup !== undefined) return markup;
|
|
88
180
|
if (!warned.has(name)) {
|
|
89
181
|
warned.add(name);
|
|
@@ -92,9 +184,16 @@ export function getIcon(name) {
|
|
|
92
184
|
return "";
|
|
93
185
|
}
|
|
94
186
|
|
|
95
|
-
/** The
|
|
96
|
-
export function
|
|
97
|
-
return
|
|
187
|
+
/** The roles the components draw ("ui.close"…) and the glyph each one uses unless registered. */
|
|
188
|
+
export function iconAliases() {
|
|
189
|
+
return { ...ALIASES };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** The registered icon names; with `filled`, those that have a filled version. */
|
|
193
|
+
export function iconNames({ filled = false } = {}) {
|
|
194
|
+
const names = [...registry.keys()];
|
|
195
|
+
if (filled) return names.filter((n) => n.endsWith(FILLED_SUFFIX)).map((n) => n.slice(0, -FILLED_SUFFIX.length));
|
|
196
|
+
return names.filter((n) => !n.endsWith(FILLED_SUFFIX));
|
|
98
197
|
}
|
|
99
198
|
|
|
100
199
|
/** @internal Called by the core runtime to repaint components after setIcons. */
|
package/core/position.js
CHANGED
|
@@ -5,12 +5,19 @@
|
|
|
5
5
|
// side when it does not fit, and shifted to stay inside the viewport.
|
|
6
6
|
// Done in JS rather than CSS anchor positioning, which not every webview
|
|
7
7
|
// ships yet (WebKitGTK, older WKWebView).
|
|
8
|
+
//
|
|
9
|
+
// The sides top/bottom/left/right are sides of the screen; the alignments
|
|
10
|
+
// -start/-end follow the writing direction of the floating element: right to
|
|
11
|
+
// left, "bottom-start" lines up the right edges.
|
|
12
|
+
|
|
13
|
+
import { isRtl } from "./direction.js";
|
|
8
14
|
|
|
9
15
|
const OPPOSITE = { top: "bottom", bottom: "top", left: "right", right: "left" };
|
|
10
16
|
|
|
11
17
|
/**
|
|
12
18
|
* @typedef {object} PlaceOptions
|
|
13
|
-
* @property {string} [placement] side[-align]: top|bottom|left|right, -start|-end (default "bottom")
|
|
19
|
+
* @property {string} [placement] side[-align]: top|bottom|left|right, -start|-end (default "bottom");
|
|
20
|
+
* on top/bottom, -start/-end follow the writing direction
|
|
14
21
|
* @property {number} [offset] gap to the anchor in px (default 8)
|
|
15
22
|
* @property {number} [padding] minimum distance to the viewport edges (default 8)
|
|
16
23
|
* @property {boolean} [flip] try the opposite side when it does not fit (default true)
|
|
@@ -45,8 +52,9 @@ export function place(anchor, floating, { placement = "bottom", offset = 8, padd
|
|
|
45
52
|
let y;
|
|
46
53
|
if (side === "top" || side === "bottom") {
|
|
47
54
|
y = side === "bottom" ? anchor.bottom + offset : anchor.top - offset - f.height;
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
const rtl = align !== "center" && isRtl(floating);
|
|
56
|
+
x = align === (rtl ? "end" : "start") ? anchor.left
|
|
57
|
+
: align === (rtl ? "start" : "end") ? anchor.right - f.width
|
|
50
58
|
: anchor.left + anchor.width / 2 - f.width / 2;
|
|
51
59
|
} else {
|
|
52
60
|
x = side === "right" ? anchor.right + offset : anchor.left - offset - f.width;
|
package/core/styles.js
CHANGED
|
@@ -154,7 +154,7 @@ export const loaderStyles = css`
|
|
|
154
154
|
width: var(--_loader, 1em);
|
|
155
155
|
height: var(--_loader, 1em);
|
|
156
156
|
border: max(2px, calc(var(--_loader, 1em) / 8)) solid currentColor;
|
|
157
|
-
border-right-color: transparent;
|
|
157
|
+
border-right-color: transparent; /* physical */
|
|
158
158
|
border-radius: 50%;
|
|
159
159
|
animation: ray-spin 0.75s linear infinite;
|
|
160
160
|
}
|
package/core.js
CHANGED
|
@@ -8,6 +8,7 @@ export { COLORS, VARIANT_TOKENS, applyColor, spaceValue, sizeStyles, radiusStyle
|
|
|
8
8
|
export { place, pointRect, autoUpdate } from "./core/position.js";
|
|
9
9
|
export { scrollerOf, watchScroll } from "./core/scroll.js";
|
|
10
10
|
export { tabbables, focusFirst } from "./core/focus.js";
|
|
11
|
+
export { isRtl, inlineKey } from "./core/direction.js";
|
|
11
12
|
export { duration, motionAllowed, play, playAll, collapseOut, POP_OUT } from "./core/motion.js";
|
|
12
13
|
export { dismissable } from "./core/dismiss.js";
|
|
13
14
|
export { matchesHotkey, formatHotkey } from "./core/hotkey.js";
|