@rvx/ui 0.1.6
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/LICENSE +21 -0
- package/dist/common/events.d.ts +72 -0
- package/dist/common/events.js +58 -0
- package/dist/common/events.js.map +1 -0
- package/dist/common/parsers.d.ts +88 -0
- package/dist/common/parsers.js +62 -0
- package/dist/common/parsers.js.map +1 -0
- package/dist/common/theme-test.d.ts +7 -0
- package/dist/common/theme-test.js +14 -0
- package/dist/common/theme-test.js.map +1 -0
- package/dist/common/theme.d.ts +144 -0
- package/dist/common/theme.js +2 -0
- package/dist/common/theme.js.map +1 -0
- package/dist/common/trim.d.ts +12 -0
- package/dist/common/trim.js +16 -0
- package/dist/common/trim.js.map +1 -0
- package/dist/common/types.d.ts +13 -0
- package/dist/common/types.js +10 -0
- package/dist/common/types.js.map +1 -0
- package/dist/common/writing-mode.d.ts +82 -0
- package/dist/common/writing-mode.js +61 -0
- package/dist/common/writing-mode.js.map +1 -0
- package/dist/components/button.d.ts +42 -0
- package/dist/components/button.js +26 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/checkbox.d.ts +9 -0
- package/dist/components/checkbox.js +32 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/collapse-test.d.ts +8 -0
- package/dist/components/collapse-test.js +15 -0
- package/dist/components/collapse-test.js.map +1 -0
- package/dist/components/collapse.d.ts +13 -0
- package/dist/components/collapse.js +44 -0
- package/dist/components/collapse.js.map +1 -0
- package/dist/components/column.d.ts +12 -0
- package/dist/components/column.js +12 -0
- package/dist/components/column.js.map +1 -0
- package/dist/components/control-group.d.ts +7 -0
- package/dist/components/control-group.js +11 -0
- package/dist/components/control-group.js.map +1 -0
- package/dist/components/dialog.d.ts +33 -0
- package/dist/components/dialog.js +67 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/dropdown-input.d.ts +27 -0
- package/dist/components/dropdown-input.js +31 -0
- package/dist/components/dropdown-input.js.map +1 -0
- package/dist/components/dropdown.d.ts +123 -0
- package/dist/components/dropdown.js +176 -0
- package/dist/components/dropdown.js.map +1 -0
- package/dist/components/flex-space.d.ts +4 -0
- package/dist/components/flex-space.js +10 -0
- package/dist/components/flex-space.js.map +1 -0
- package/dist/components/heading.d.ts +9 -0
- package/dist/components/heading.js +14 -0
- package/dist/components/heading.js.map +1 -0
- package/dist/components/label.d.ts +14 -0
- package/dist/components/label.js +15 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/layer.d.ts +81 -0
- package/dist/components/layer.js +164 -0
- package/dist/components/layer.js.map +1 -0
- package/dist/components/link.d.ts +57 -0
- package/dist/components/link.js +26 -0
- package/dist/components/link.js.map +1 -0
- package/dist/components/page.d.ts +9 -0
- package/dist/components/page.js +17 -0
- package/dist/components/page.js.map +1 -0
- package/dist/components/popout.d.ts +134 -0
- package/dist/components/popout.js +259 -0
- package/dist/components/popout.js.map +1 -0
- package/dist/components/popover.d.ts +139 -0
- package/dist/components/popover.js +101 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/radio-buttons.d.ts +17 -0
- package/dist/components/radio-buttons.js +26 -0
- package/dist/components/radio-buttons.js.map +1 -0
- package/dist/components/row.d.ts +10 -0
- package/dist/components/row.js +23 -0
- package/dist/components/row.js.map +1 -0
- package/dist/components/scroll-view.d.ts +6 -0
- package/dist/components/scroll-view.js +72 -0
- package/dist/components/scroll-view.js.map +1 -0
- package/dist/components/text-input.d.ts +53 -0
- package/dist/components/text-input.js +35 -0
- package/dist/components/text-input.js.map +1 -0
- package/dist/components/text.d.ts +7 -0
- package/dist/components/text.js +11 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/validation.d.ts +109 -0
- package/dist/components/validation.js +151 -0
- package/dist/components/validation.js.map +1 -0
- package/dist/components/value.d.ts +7 -0
- package/dist/components/value.js +11 -0
- package/dist/components/value.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/test.d.ts +2 -0
- package/dist/test.js +3 -0
- package/dist/test.js.map +1 -0
- package/dist/theme.module.css +679 -0
- package/dist/theme.module.css.map +1 -0
- package/package.json +29 -0
- package/src/common/events.tsx +130 -0
- package/src/common/parsers.tsx +167 -0
- package/src/common/theme-test.tsx +20 -0
- package/src/common/theme.tsx +165 -0
- package/src/common/trim.tsx +30 -0
- package/src/common/types.tsx +23 -0
- package/src/common/writing-mode.tsx +150 -0
- package/src/components/button.tsx +94 -0
- package/src/components/checkbox.tsx +64 -0
- package/src/components/collapse-test.tsx +23 -0
- package/src/components/collapse.tsx +75 -0
- package/src/components/column.tsx +28 -0
- package/src/components/control-group.tsx +22 -0
- package/src/components/dialog.tsx +137 -0
- package/src/components/dropdown-input.tsx +82 -0
- package/src/components/dropdown.tsx +352 -0
- package/src/components/flex-space.tsx +15 -0
- package/src/components/heading.tsx +23 -0
- package/src/components/label.tsx +37 -0
- package/src/components/layer.tsx +299 -0
- package/src/components/link.tsx +118 -0
- package/src/components/page.tsx +36 -0
- package/src/components/popout.tsx +461 -0
- package/src/components/popover.tsx +292 -0
- package/src/components/radio-buttons.tsx +81 -0
- package/src/components/row.tsx +37 -0
- package/src/components/scroll-view.tsx +97 -0
- package/src/components/text-input.tsx +117 -0
- package/src/components/text.tsx +22 -0
- package/src/components/validation.tsx +272 -0
- package/src/components/value.tsx +22 -0
- package/src/index.tsx +29 -0
- package/src/test.tsx +2 -0
- package/src/theme/base.scss +69 -0
- package/src/theme/common.scss +51 -0
- package/src/theme/components/button.scss +116 -0
- package/src/theme/components/checkbox.scss +25 -0
- package/src/theme/components/collapse.scss +64 -0
- package/src/theme/components/column.scss +28 -0
- package/src/theme/components/control-group.scss +14 -0
- package/src/theme/components/dialog.scss +44 -0
- package/src/theme/components/dropdown.scss +50 -0
- package/src/theme/components/flex-space.scss +6 -0
- package/src/theme/components/heading.scss +39 -0
- package/src/theme/components/label.scss +24 -0
- package/src/theme/components/link.scss +25 -0
- package/src/theme/components/page.scss +22 -0
- package/src/theme/components/popover.scss +58 -0
- package/src/theme/components/radio-buttons.scss +31 -0
- package/src/theme/components/row.scss +17 -0
- package/src/theme/components/scroll-view.scss +51 -0
- package/src/theme/components/text-input.scss +45 -0
- package/src/theme/components/text.scss +12 -0
- package/src/theme/components/validation.scss +15 -0
- package/src/theme/components/value.scss +4 -0
- package/src/theme/theme.scss +22 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { ClassValue, Expression, extract, For, get, map, memo, optionalString, render, sig, StyleValue, uniqueId, View, watch } from "rvx";
|
|
2
|
+
|
|
3
|
+
import { Action, createPassiveActionEvent, handleActionEvent, keyFor, startDelayedHoverOnMouseenter } from "../common/events.js";
|
|
4
|
+
import { THEME } from "../common/theme.js";
|
|
5
|
+
import { LAYER } from "./layer.js";
|
|
6
|
+
import { Popout, PopoutAlignment, PopoutPlacement } from "./popout.js";
|
|
7
|
+
|
|
8
|
+
export interface DropdownItem {
|
|
9
|
+
/**
|
|
10
|
+
* The item label.
|
|
11
|
+
*/
|
|
12
|
+
label: unknown;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The action to run when this item is selected.
|
|
16
|
+
*/
|
|
17
|
+
action?: Action;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Optional child items.
|
|
21
|
+
*
|
|
22
|
+
* + If an action is also specified and runs when the item is selected, this is only accessible by hovering or pressing `ArrowRight`.
|
|
23
|
+
* + This expression is memoized and only evaluated while the dropdown is open.
|
|
24
|
+
*/
|
|
25
|
+
children?: Expression<DropdownItem[]>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* True if this item is currently selected.
|
|
29
|
+
*/
|
|
30
|
+
selected?: Expression<boolean>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Create a dropdown that is initially hidden.
|
|
35
|
+
*/
|
|
36
|
+
export function createDropdown(props: {
|
|
37
|
+
/**
|
|
38
|
+
* The items contained in this dropdown.
|
|
39
|
+
*
|
|
40
|
+
* This expression is memoized and only evaluated while the dropdown is open.
|
|
41
|
+
*/
|
|
42
|
+
items: Expression<DropdownItem[]>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* True to indicate, that this is a nested dropdown.
|
|
46
|
+
*
|
|
47
|
+
* Currently, this allows the dropdown to be closed by pressing "ArrowRight".
|
|
48
|
+
*/
|
|
49
|
+
expansion?: boolean;
|
|
50
|
+
|
|
51
|
+
/** An id for the dropdown root. */
|
|
52
|
+
id?: Expression<string | undefined>;
|
|
53
|
+
/** Styles for the dropdown root. */
|
|
54
|
+
style?: StyleValue;
|
|
55
|
+
/** Classes for the dropdown root. */
|
|
56
|
+
class?: ClassValue;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Defines the direction in which the dropdown is placed in relation to the anchor.
|
|
60
|
+
*
|
|
61
|
+
* This expression is only evaluated when calculating the dropdown placement.
|
|
62
|
+
*
|
|
63
|
+
* See {@link PopoutPlacement}
|
|
64
|
+
*
|
|
65
|
+
* @default "block-end"
|
|
66
|
+
*/
|
|
67
|
+
placement?: Expression<PopoutPlacement | undefined>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Defines which side of the anchor and popover are aligned orthogonally to the placement axis.
|
|
71
|
+
*
|
|
72
|
+
* This expression is only evaluated when calculating the popover placement.
|
|
73
|
+
*
|
|
74
|
+
* See {@link PopoutAlignment}
|
|
75
|
+
*
|
|
76
|
+
* @default "start"
|
|
77
|
+
*/
|
|
78
|
+
alignment?: Expression<PopoutAlignment | undefined>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* An array of event names that cause the dropdown to hide automatically when dispatched outside of the current layer stack or the anchor.
|
|
82
|
+
*
|
|
83
|
+
* @default ["resize", "scroll", "mousedown", "touchstart", "focusin", "rvx-ui:passive-action"]
|
|
84
|
+
*/
|
|
85
|
+
foreignEvents?: string[];
|
|
86
|
+
}): Popout {
|
|
87
|
+
return new Popout({
|
|
88
|
+
placement: map(props.placement, v => v ?? "block-end"),
|
|
89
|
+
alignment: map(props.alignment, v => v ?? "start"),
|
|
90
|
+
foreignEvents: props.foreignEvents,
|
|
91
|
+
content: ({ popout, placement }) => {
|
|
92
|
+
const theme = extract(THEME);
|
|
93
|
+
const layer = extract(LAYER)!;
|
|
94
|
+
|
|
95
|
+
const activeItem = sig<DropdownItem | undefined>(undefined);
|
|
96
|
+
const instances = new WeakMap<DropdownItem, {
|
|
97
|
+
id: string;
|
|
98
|
+
children: Popout | undefined;
|
|
99
|
+
root: HTMLElement;
|
|
100
|
+
view: View;
|
|
101
|
+
}>();
|
|
102
|
+
|
|
103
|
+
const items = memo(props.items);
|
|
104
|
+
watch(items, items => {
|
|
105
|
+
const current = activeItem.value;
|
|
106
|
+
if (current !== undefined && !items.includes(current)) {
|
|
107
|
+
activeItem.value = undefined;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const scrollToActive = () => {
|
|
112
|
+
const active = activeItem.value;
|
|
113
|
+
if (active) {
|
|
114
|
+
instances.get(active)?.root.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
layer.useEvent("keydown", event => {
|
|
119
|
+
const currentItems = items();
|
|
120
|
+
const current = activeItem.value;
|
|
121
|
+
switch (keyFor(event)) {
|
|
122
|
+
case "escape": {
|
|
123
|
+
popout.hide();
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
case "arrowleft": {
|
|
127
|
+
if (props.expansion) {
|
|
128
|
+
popout.hide();
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
case "arrowdown": {
|
|
134
|
+
activeItem.value = currentItems[(current === undefined ? 0 : (currentItems.indexOf(current) + 1)) % currentItems.length];
|
|
135
|
+
scrollToActive();
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
case "arrowup": {
|
|
139
|
+
const index = current === undefined ? -1 : (currentItems.indexOf(current) - 1);
|
|
140
|
+
activeItem.value = currentItems[index < 0 ? currentItems.length - 1 : index];
|
|
141
|
+
scrollToActive();
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case "arrowright": {
|
|
145
|
+
if (current) {
|
|
146
|
+
const instance = instances.get(current);
|
|
147
|
+
if (instance?.children) {
|
|
148
|
+
instance.children.show(instance.view, event);
|
|
149
|
+
event.stopImmediatePropagation();
|
|
150
|
+
event.preventDefault();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case "enter": {
|
|
156
|
+
if (current?.action && handleActionEvent(event, current.action)) {
|
|
157
|
+
popout.hide();
|
|
158
|
+
} else if (current) {
|
|
159
|
+
const instance = instances.get(current);
|
|
160
|
+
if (instance?.children) {
|
|
161
|
+
instance.children.show(instance.view, event);
|
|
162
|
+
event.stopImmediatePropagation();
|
|
163
|
+
event.preventDefault();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
default: return;
|
|
169
|
+
}
|
|
170
|
+
event.stopImmediatePropagation();
|
|
171
|
+
event.preventDefault();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const content = <div class={[
|
|
175
|
+
theme?.dropdown_content,
|
|
176
|
+
]}>
|
|
177
|
+
<For each={items}>
|
|
178
|
+
{item => {
|
|
179
|
+
const id = uniqueId();
|
|
180
|
+
|
|
181
|
+
let childrenId: string | undefined;
|
|
182
|
+
let children: Popout | undefined;
|
|
183
|
+
if (item.children) {
|
|
184
|
+
childrenId = uniqueId();
|
|
185
|
+
children = createDropdown({
|
|
186
|
+
placement: () => {
|
|
187
|
+
const parentPlacement = get(placement)?.placement;
|
|
188
|
+
if (parentPlacement === "block-end" || parentPlacement === "block-start") {
|
|
189
|
+
return "inline-end";
|
|
190
|
+
}
|
|
191
|
+
return parentPlacement ?? "inline-end";
|
|
192
|
+
},
|
|
193
|
+
alignment: props.alignment,
|
|
194
|
+
items: item.children,
|
|
195
|
+
expansion: true,
|
|
196
|
+
foreignEvents: props.foreignEvents,
|
|
197
|
+
class: props.class,
|
|
198
|
+
style: props.style,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const root = <div
|
|
203
|
+
id={id}
|
|
204
|
+
class={[
|
|
205
|
+
theme?.dropdown_item,
|
|
206
|
+
() => activeItem.value === item && theme?.dropdown_item_active,
|
|
207
|
+
]}
|
|
208
|
+
role="option"
|
|
209
|
+
aria-selected={item.selected}
|
|
210
|
+
aria-haspopup={children ? "listbox" : undefined}
|
|
211
|
+
aria-controls={() => children?.visible ? childrenId : undefined}
|
|
212
|
+
aria-expanded={optionalString(() => children?.visible)}
|
|
213
|
+
on:click={event => {
|
|
214
|
+
activeItem.value = item;
|
|
215
|
+
if (item.action && handleActionEvent(event, item.action)) {
|
|
216
|
+
popout.hide();
|
|
217
|
+
} else if (children) {
|
|
218
|
+
children.show(view, event);
|
|
219
|
+
event.stopImmediatePropagation();
|
|
220
|
+
event.preventDefault();
|
|
221
|
+
}
|
|
222
|
+
}}
|
|
223
|
+
on:mouseenter={event => {
|
|
224
|
+
activeItem.value = item;
|
|
225
|
+
startDelayedHoverOnMouseenter(event, () => {
|
|
226
|
+
event.target?.dispatchEvent(createPassiveActionEvent());
|
|
227
|
+
if (activeItem.value === item) {
|
|
228
|
+
children?.show(view, event);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}}
|
|
232
|
+
>
|
|
233
|
+
{item.label}
|
|
234
|
+
</div> as HTMLElement;
|
|
235
|
+
const view = render(root);
|
|
236
|
+
instances.set(item, { id, children, root, view });
|
|
237
|
+
return view;
|
|
238
|
+
}}
|
|
239
|
+
</For>
|
|
240
|
+
</div>;
|
|
241
|
+
|
|
242
|
+
const root = <div
|
|
243
|
+
id={props.id}
|
|
244
|
+
style={props.style}
|
|
245
|
+
class={[
|
|
246
|
+
props.class,
|
|
247
|
+
theme?.dropdown,
|
|
248
|
+
map(props.expansion, v => v && theme?.dropdown_expansion),
|
|
249
|
+
]}
|
|
250
|
+
role="listbox"
|
|
251
|
+
tabindex="0"
|
|
252
|
+
aria-activedescendant={() => {
|
|
253
|
+
const item = activeItem.value;
|
|
254
|
+
return item === undefined ? undefined : instances.get(item)?.id;
|
|
255
|
+
}}
|
|
256
|
+
on:focus={() => {
|
|
257
|
+
if (!activeItem.value) {
|
|
258
|
+
const currentItems = items();
|
|
259
|
+
activeItem.value = currentItems.find(v => get(v.selected)) ?? currentItems[0];
|
|
260
|
+
}
|
|
261
|
+
}}
|
|
262
|
+
>
|
|
263
|
+
<div class={theme?.dropdown_scroll_area}>
|
|
264
|
+
{content}
|
|
265
|
+
</div>
|
|
266
|
+
</div> as HTMLElement;
|
|
267
|
+
layer.useAutoFocusFallback(root);
|
|
268
|
+
return root;
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface DropdownAnchorProps {
|
|
274
|
+
action: Action;
|
|
275
|
+
"aria-haspopup": Expression<string | undefined>;
|
|
276
|
+
"aria-controls": Expression<string | undefined>;
|
|
277
|
+
"aria-expanded": Expression<boolean>;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function Dropdown(props: {
|
|
281
|
+
/**
|
|
282
|
+
* A function to immediately render the anchor.
|
|
283
|
+
*/
|
|
284
|
+
anchor: (props: DropdownAnchorProps) => unknown;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* The items contained in this dropdown.
|
|
288
|
+
*
|
|
289
|
+
* This expression is memoized and only evaluated while the dropdown is open.
|
|
290
|
+
*/
|
|
291
|
+
items: Expression<DropdownItem[]>;
|
|
292
|
+
|
|
293
|
+
/** An id for the dropdown root. */
|
|
294
|
+
id?: Expression<string | undefined>;
|
|
295
|
+
/** Styles for the dropdown root. */
|
|
296
|
+
style?: StyleValue;
|
|
297
|
+
/** Classes for the dropdown root. */
|
|
298
|
+
class?: ClassValue;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Defines the direction in which the dropdown is placed in relation to the anchor.
|
|
302
|
+
*
|
|
303
|
+
* This expression is only evaluated when calculating the dropdown placement.
|
|
304
|
+
*
|
|
305
|
+
* See {@link PopoutPlacement}
|
|
306
|
+
*
|
|
307
|
+
* @default "block-end"
|
|
308
|
+
*/
|
|
309
|
+
placement?: Expression<PopoutPlacement | undefined>;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Defines which side of the anchor and popover are aligned orthogonally to the placement axis.
|
|
313
|
+
*
|
|
314
|
+
* This expression is only evaluated when calculating the popover placement.
|
|
315
|
+
*
|
|
316
|
+
* See {@link PopoutAlignment}
|
|
317
|
+
*
|
|
318
|
+
* @default "start"
|
|
319
|
+
*/
|
|
320
|
+
alignment?: Expression<PopoutAlignment | undefined>;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* An array of event names that cause the dropdown to hide automatically when dispatched outside of the current layer stack or the anchor.
|
|
324
|
+
*
|
|
325
|
+
* @default ["resize", "scroll", "mousedown", "touchstart", "focusin", "rvx-ui:passive-action"]
|
|
326
|
+
*/
|
|
327
|
+
foreignEvents?: string[];
|
|
328
|
+
}): unknown {
|
|
329
|
+
const defaultId = uniqueId();
|
|
330
|
+
const id = map(props.id, v => v ?? defaultId);
|
|
331
|
+
|
|
332
|
+
const dropdown = createDropdown({
|
|
333
|
+
items: props.items,
|
|
334
|
+
id,
|
|
335
|
+
style: props.style,
|
|
336
|
+
class: props.class,
|
|
337
|
+
placement: props.placement,
|
|
338
|
+
alignment: props.alignment,
|
|
339
|
+
foreignEvents: props.foreignEvents,
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const anchor = render(props.anchor({
|
|
343
|
+
action: event => {
|
|
344
|
+
dropdown.toggle(anchor, event);
|
|
345
|
+
},
|
|
346
|
+
"aria-haspopup": "listbox",
|
|
347
|
+
"aria-controls": () => dropdown.visible ? get(id) : undefined,
|
|
348
|
+
"aria-expanded": () => dropdown.visible,
|
|
349
|
+
}));
|
|
350
|
+
|
|
351
|
+
return anchor;
|
|
352
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Expression, extract, get } from "rvx";
|
|
2
|
+
|
|
3
|
+
import { THEME } from "../common/theme.js";
|
|
4
|
+
|
|
5
|
+
export function FlexSpace(props: {
|
|
6
|
+
grow?: Expression<number | undefined>;
|
|
7
|
+
}): unknown {
|
|
8
|
+
const theme = extract(THEME);
|
|
9
|
+
return <div
|
|
10
|
+
class={theme?.flex_space}
|
|
11
|
+
style={{
|
|
12
|
+
"flex-grow": () => String(get(props.grow) ?? 1),
|
|
13
|
+
}}
|
|
14
|
+
/>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ClassValue, createElement, Expression, extract, StyleValue } from "rvx";
|
|
2
|
+
|
|
3
|
+
import { THEME } from "../common/theme.js";
|
|
4
|
+
|
|
5
|
+
export type HeadingLevel = "1" | "2" | "3" | "4" | "5" | "6";
|
|
6
|
+
|
|
7
|
+
export function Heading(props: {
|
|
8
|
+
level: HeadingLevel;
|
|
9
|
+
class?: ClassValue;
|
|
10
|
+
style?: StyleValue;
|
|
11
|
+
id?: Expression<string | undefined>;
|
|
12
|
+
children?: unknown;
|
|
13
|
+
}): unknown {
|
|
14
|
+
const theme = extract(THEME);
|
|
15
|
+
return createElement(`h${props.level}`, {
|
|
16
|
+
class: [
|
|
17
|
+
theme?.heading,
|
|
18
|
+
props.class,
|
|
19
|
+
],
|
|
20
|
+
style: props.style,
|
|
21
|
+
id: props.id,
|
|
22
|
+
}, props.children);
|
|
23
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ClassValue, Expression, extract, StyleValue, uniqueId } from "rvx";
|
|
2
|
+
|
|
3
|
+
import { THEME } from "../common/theme.js";
|
|
4
|
+
|
|
5
|
+
export function Label(props: {
|
|
6
|
+
class?: ClassValue;
|
|
7
|
+
style?: StyleValue;
|
|
8
|
+
for?: Expression<string | undefined>;
|
|
9
|
+
id?: Expression<string | undefined>;
|
|
10
|
+
children?: unknown;
|
|
11
|
+
}): unknown {
|
|
12
|
+
const theme = extract(THEME);
|
|
13
|
+
return <label
|
|
14
|
+
class={[
|
|
15
|
+
theme?.label,
|
|
16
|
+
props.class,
|
|
17
|
+
]}
|
|
18
|
+
style={props.style}
|
|
19
|
+
for={props.for}
|
|
20
|
+
id={props.id}
|
|
21
|
+
>
|
|
22
|
+
{props.children}
|
|
23
|
+
</label>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function LabelFor(props: {
|
|
27
|
+
class?: ClassValue;
|
|
28
|
+
style?: StyleValue;
|
|
29
|
+
label: unknown;
|
|
30
|
+
children: (id: string) => unknown;
|
|
31
|
+
}): unknown {
|
|
32
|
+
const id = uniqueId();
|
|
33
|
+
return <>
|
|
34
|
+
<Label class={props.class} style={props.style} for={id}>{props.label}</Label>
|
|
35
|
+
{props.children(id)}
|
|
36
|
+
</>;
|
|
37
|
+
}
|