@vanilla-bean/components 1.1.1 → 2.0.1
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/Component/Component.js +222 -36
- package/Component/Component.test.js +425 -38
- package/Component/README.md +480 -0
- package/Elem/README.md +373 -0
- package/README.md +1 -1
- package/components/BottomSheet/BottomSheet.js +8 -16
- package/components/Button/Button.js +12 -18
- package/components/Calendar/Calendar.js +139 -59
- package/components/Calendar/CalendarEvent.js +9 -4
- package/components/Calendar/Toolbar.js +28 -20
- package/components/Calendar/index.js +1 -0
- package/components/Code/Code.js +26 -30
- package/components/ColorPicker/ColorPicker.js +57 -57
- package/components/Dialog/Dialog.js +78 -72
- package/components/Form/Form.js +12 -8
- package/components/Icon/Icon.js +19 -11
- package/components/Input/Input.js +85 -67
- package/components/Input/README.md +0 -2
- package/components/Keyboard/Key.js +7 -10
- package/components/Keyboard/Keyboard.js +38 -46
- package/components/Label/Label.js +52 -50
- package/components/Link/Link.js +14 -20
- package/components/List/List.js +28 -30
- package/components/Menu/Menu.js +19 -10
- package/components/Menu/Menu.lld.md +2 -2
- package/components/Notify/Notify.js +29 -19
- package/components/Popover/Popover.js +49 -44
- package/components/RadioButton/RadioButton.js +33 -29
- package/components/Router/Router.js +19 -21
- package/components/Select/Select.js +24 -30
- package/components/Table/Table.js +55 -36
- package/components/TagList/Tag.js +16 -14
- package/components/TagList/TagList.js +15 -8
- package/components/Tooltip/Tooltip.js +12 -25
- package/components/TooltipWrapper/TooltipWrapper.js +55 -49
- package/components/Whiteboard/Whiteboard.js +45 -43
- package/devTools/build.js +43 -0
- package/devTools/buildTypes.js +322 -0
- package/devTools/createComponent.js +155 -0
- package/devTools/extractJSDoc.js +395 -0
- package/devTools/processTemplate.js +500 -0
- package/devTools/updateComponentIndex.js +16 -0
- package/devTools/updateDemoViewIndex.js +90 -0
- package/eslint.config.cjs +6 -3
- package/index.d.ts +117 -59
- package/package.json +67 -22
- package/spellcheck.config.cjs +4 -0
- package/styled/README.md +329 -0
- package/theme/colors.js +15 -12
- package/theme/colors.test.js +28 -0
- package/utils/element.js +2 -2
- package/FontWithASyntaxHighlighter-Regular.woff2 +0 -0
|
@@ -120,10 +120,6 @@ const StyledLabel = styled(
|
|
|
120
120
|
`,
|
|
121
121
|
);
|
|
122
122
|
|
|
123
|
-
const variant_enum = Object.freeze(['overlay', 'collapsible', 'inline', 'inline-after', 'simple']);
|
|
124
|
-
|
|
125
|
-
const defaultOptions = { variant: 'simple' };
|
|
126
|
-
|
|
127
123
|
/**
|
|
128
124
|
* Label component with multiple display variants and input association.
|
|
129
125
|
*
|
|
@@ -139,20 +135,61 @@ const defaultOptions = { variant: 'simple' };
|
|
|
139
135
|
* @returns {Label} Label component instance
|
|
140
136
|
*/
|
|
141
137
|
class Label extends StyledLabel {
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
static schema = {
|
|
139
|
+
variant: {
|
|
140
|
+
default: 'simple',
|
|
141
|
+
enum: ['overlay', 'collapsible', 'inline', 'inline-after', 'simple'],
|
|
142
|
+
set(value) {
|
|
143
|
+
this.removeClass(/\bvariant-\S+\b/g);
|
|
144
|
+
this.addClass(`variant-${value}`);
|
|
145
|
+
|
|
146
|
+
if (this._labelText) {
|
|
147
|
+
const shouldBeAfter = value === 'inline-after';
|
|
148
|
+
const isAfter = this._labelText.elem === this.elem.lastElementChild;
|
|
149
|
+
if (shouldBeAfter !== isAfter) this[shouldBeAfter ? 'append' : 'prepend'](this._labelText);
|
|
150
|
+
if (value === 'collapsible') {
|
|
151
|
+
this._labelText.elem.setAttribute('aria-expanded', this.hasClass('collapsed') ? 'false' : 'true');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
label: {
|
|
157
|
+
set(value) {
|
|
158
|
+
if (typeof value === 'object') this._labelText?.setOptions(value);
|
|
159
|
+
else if (this._labelText) this._labelText.options.content = value;
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
collapsed: {
|
|
163
|
+
set(value) {
|
|
164
|
+
this[value ? 'addClass' : 'removeClass']('collapsed');
|
|
165
|
+
if (this.options.variant === 'collapsible' && this._labelText) {
|
|
166
|
+
this._labelText.elem.setAttribute('aria-expanded', value ? 'false' : 'true');
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
for: {
|
|
171
|
+
set(value) {
|
|
172
|
+
let forId = typeof value === 'string' ? value : value?.id || value?.elem?.id;
|
|
144
173
|
|
|
145
|
-
|
|
146
|
-
|
|
174
|
+
if (!forId && value?._component) {
|
|
175
|
+
forId = value.elem.id = value.uniqueId;
|
|
176
|
+
}
|
|
147
177
|
|
|
148
|
-
|
|
149
|
-
{
|
|
150
|
-
...(children.length > 0 && { for: children[0] }),
|
|
151
|
-
...defaultOptions,
|
|
152
|
-
...options,
|
|
178
|
+
if (this._labelText) this._labelText.elem.htmlFor = forId ?? '';
|
|
153
179
|
},
|
|
154
|
-
|
|
155
|
-
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
static prepareOptions(options, children) {
|
|
184
|
+
return {
|
|
185
|
+
...(children.length > 0 && { for: children[0] }),
|
|
186
|
+
...options,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
constructor(options = {}, ...children) {
|
|
191
|
+
// String shorthand must resolve before Component spreads options
|
|
192
|
+
super(typeof options === 'string' ? { label: options } : options, ...children);
|
|
156
193
|
}
|
|
157
194
|
|
|
158
195
|
build() {
|
|
@@ -174,41 +211,6 @@ class Label extends StyledLabel {
|
|
|
174
211
|
|
|
175
212
|
this[this.options.variant === 'inline-after' ? 'append' : 'prepend'](this._labelText);
|
|
176
213
|
}
|
|
177
|
-
|
|
178
|
-
static handlers = {
|
|
179
|
-
label(value) {
|
|
180
|
-
if (typeof value === 'object') this._labelText?.setOptions(value);
|
|
181
|
-
else if (this._labelText) this._labelText.options.content = value;
|
|
182
|
-
},
|
|
183
|
-
collapsed(value) {
|
|
184
|
-
this[value ? 'addClass' : 'removeClass']('collapsed');
|
|
185
|
-
if (this.options.variant === 'collapsible' && this._labelText) {
|
|
186
|
-
this._labelText.elem.setAttribute('aria-expanded', value ? 'false' : 'true');
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
variant(value) {
|
|
190
|
-
this.removeClass(/\bvariant-\S+\b/g);
|
|
191
|
-
this.addClass(`variant-${value}`);
|
|
192
|
-
|
|
193
|
-
if (this._labelText) {
|
|
194
|
-
const shouldBeAfter = value === 'inline-after';
|
|
195
|
-
const isAfter = this._labelText.elem === this.elem.lastElementChild;
|
|
196
|
-
if (shouldBeAfter !== isAfter) this[shouldBeAfter ? 'append' : 'prepend'](this._labelText);
|
|
197
|
-
if (value === 'collapsible') {
|
|
198
|
-
this._labelText.elem.setAttribute('aria-expanded', this.hasClass('collapsed') ? 'false' : 'true');
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
|
-
for(value) {
|
|
203
|
-
let forId = typeof value === 'string' ? value : value?.id || value?.elem?.id;
|
|
204
|
-
|
|
205
|
-
if (!forId && value?._component) {
|
|
206
|
-
forId = value.elem.id = value.uniqueId;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (this._labelText) this._labelText.elem.htmlFor = forId ?? '';
|
|
210
|
-
},
|
|
211
|
-
};
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
export default Label;
|
package/components/Link/Link.js
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import { TooltipWrapper } from '../TooltipWrapper';
|
|
2
2
|
|
|
3
|
-
const defaultOptions = {
|
|
4
|
-
tag: 'a',
|
|
5
|
-
variant: 'link',
|
|
6
|
-
get tooltip() {
|
|
7
|
-
return { icon: 'link', style: { fontSize: '12px' } };
|
|
8
|
-
},
|
|
9
|
-
};
|
|
10
|
-
const variant_enum = Object.freeze(['link', 'button']);
|
|
11
|
-
|
|
12
3
|
/**
|
|
13
4
|
* Link component with tooltip support and display variants.
|
|
14
5
|
*
|
|
@@ -25,17 +16,20 @@ const variant_enum = Object.freeze(['link', 'button']);
|
|
|
25
16
|
* @returns {Link} Link component instance
|
|
26
17
|
*/
|
|
27
18
|
class Link extends TooltipWrapper {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
19
|
+
static schema = {
|
|
20
|
+
tag: { default: 'a' },
|
|
21
|
+
variant: {
|
|
22
|
+
default: 'link',
|
|
23
|
+
enum: ['link', 'button'],
|
|
24
|
+
set(value) {
|
|
25
|
+
this.removeClass(/\bvariant-\S+\b/g);
|
|
26
|
+
this.addClass(`variant-${value}`);
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
tooltip: {
|
|
30
|
+
get default() {
|
|
31
|
+
return { icon: 'link', style: { fontSize: '12px' } };
|
|
32
|
+
},
|
|
39
33
|
},
|
|
40
34
|
};
|
|
41
35
|
}
|
package/components/List/List.js
CHANGED
|
@@ -42,41 +42,39 @@ const ListItem = styled(
|
|
|
42
42
|
* @returns {List} List component instance
|
|
43
43
|
*/
|
|
44
44
|
export default class List extends StyledComponent {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
static schema = {
|
|
46
|
+
tag: { default: 'ul' },
|
|
47
|
+
noStyle: {
|
|
48
|
+
set(value) {
|
|
49
|
+
this.toggleClass('no-style', !!value);
|
|
50
50
|
},
|
|
51
|
-
...children,
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
static handlers = {
|
|
56
|
-
noStyle(value) {
|
|
57
|
-
this.toggleClass('no-style', !!value);
|
|
58
51
|
},
|
|
59
|
-
items
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
52
|
+
items: {
|
|
53
|
+
set(value) {
|
|
54
|
+
if (!value) {
|
|
55
|
+
this.empty();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
this.content(
|
|
60
|
+
value.map(item => {
|
|
61
|
+
const isContent = typeof item === 'string' || item?.elem || Array.isArray(item);
|
|
62
|
+
const listItem = new ListItem({ tag: 'li', ...item?.listItemOptions });
|
|
63
|
+
// listItemOptions belongs to the li wrapper - strip it before passing item options along.
|
|
64
|
+
const itemOptions = isContent ? item : { ...item };
|
|
65
|
+
if (!isContent) delete itemOptions.listItemOptions;
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
if (this.options.ListItemComponent) {
|
|
68
|
+
listItem.content(new this.options.ListItemComponent(isContent ? { content: item } : itemOptions));
|
|
69
|
+
} else if (item.ListItemComponent) {
|
|
70
|
+
listItem.content(new item.ListItemComponent(itemOptions));
|
|
71
|
+
} else if (isContent) listItem.content(item);
|
|
72
|
+
else listItem.setOptions(itemOptions);
|
|
76
73
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
return listItem;
|
|
75
|
+
}),
|
|
76
|
+
);
|
|
77
|
+
},
|
|
80
78
|
},
|
|
81
79
|
};
|
|
82
80
|
}
|
package/components/Menu/Menu.js
CHANGED
|
@@ -37,23 +37,32 @@ const StyledList = styled(
|
|
|
37
37
|
* borders, and click handling. Provides consistent menu appearance and behavior.
|
|
38
38
|
* @param {object} [options={}] - Menu configuration options
|
|
39
39
|
* @param {Array<*>} [options.items] - Array of menu items to render
|
|
40
|
-
* @param {Function} [options.onSelect] - Handler
|
|
40
|
+
* @param {Function} [options.onSelect] - Handler for the "select" CustomEvent fired when a menu item is activated; the activation event is in event.detail
|
|
41
41
|
* @param {Component} [options.ListItemComponent] - Custom component class for rendering menu items
|
|
42
42
|
* @param {...(Component|HTMLElement|string)} children - Child elements to append
|
|
43
43
|
* @returns {Menu} Menu component instance
|
|
44
44
|
*/
|
|
45
45
|
export default class Menu extends StyledList {
|
|
46
|
-
static
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
static schema = {
|
|
47
|
+
role: { default: 'menu' },
|
|
48
|
+
items: {
|
|
49
|
+
set(value, next) {
|
|
50
|
+
next(value);
|
|
51
|
+
if (!value) return;
|
|
52
|
+
const items = Array.from(this.elem.children).filter(el => el.tagName === 'LI');
|
|
53
|
+
items.forEach((li, i) => li.setAttribute('tabindex', i === 0 ? '0' : '-1'));
|
|
54
|
+
},
|
|
52
55
|
},
|
|
53
56
|
};
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
static events = ['select'];
|
|
59
|
+
|
|
60
|
+
build() {
|
|
61
|
+
this.on({
|
|
62
|
+
targetEvent: 'pointerdown',
|
|
63
|
+
id: 'menuSelect',
|
|
64
|
+
callback: event => this.emit('select', event),
|
|
65
|
+
});
|
|
57
66
|
|
|
58
67
|
this.on({
|
|
59
68
|
targetEvent: 'keydown',
|
|
@@ -78,7 +87,7 @@ export default class Menu extends StyledList {
|
|
|
78
87
|
next = items[items.length - 1];
|
|
79
88
|
} else if ((e.key === 'Enter' || e.key === ' ') && currentIndex >= 0) {
|
|
80
89
|
e.preventDefault();
|
|
81
|
-
this.
|
|
90
|
+
this.emit('select', e);
|
|
82
91
|
return;
|
|
83
92
|
}
|
|
84
93
|
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
> ./Menu.js
|
|
4
4
|
|
|
5
|
-
Styled list whose items
|
|
5
|
+
Styled list whose items emit a registered `select` CustomEvent, with the activation event in `detail`. The design decision: Menu routes selection through the same unified pointer+keyboard activation path as Button; keyboard and pointer users get the same experience without separate handlers. `onSelect` is the option-form listener for the event.
|
|
6
6
|
|
|
7
7
|
## Selecting a menu item works the same way regardless of input method
|
|
8
8
|
|
|
9
|
-
- clicking, touching, Space/Enter, and screen reader activation all
|
|
9
|
+
- clicking, touching, Space/Enter, and screen reader activation all emit `select`; one handler, no separate keyboard path
|
|
10
10
|
- does clicking a menu item invoke onSelect?
|
|
11
11
|
|
|
12
12
|
## Menu renders any item format that List supports
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { styled } from '../../styled';
|
|
2
2
|
import { Popover } from '../Popover';
|
|
3
3
|
|
|
4
|
-
const type_enum = Object.freeze(['info', 'success', 'warning', 'error']);
|
|
5
|
-
|
|
6
4
|
const StyledPopover = styled(
|
|
7
5
|
Popover,
|
|
8
6
|
({ colors, fonts }) => `
|
|
@@ -68,29 +66,41 @@ const StyledPopover = styled(
|
|
|
68
66
|
* @returns {Notify} Notify component instance
|
|
69
67
|
*/
|
|
70
68
|
export default class Notify extends StyledPopover {
|
|
71
|
-
|
|
69
|
+
static schema = {
|
|
70
|
+
type: { default: 'success', enum: ['info', 'success', 'warning', 'error'] },
|
|
71
|
+
timeout: {
|
|
72
|
+
set(value) {
|
|
73
|
+
clearTimeout(this.timeout);
|
|
74
|
+
if (!value) return;
|
|
75
|
+
this.timeout = setTimeout(() => this.destroy(), value);
|
|
76
|
+
this.replaceCleanup('timeout', () => clearTimeout(this.timeout));
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
};
|
|
72
80
|
|
|
73
|
-
|
|
74
|
-
const {
|
|
75
|
-
const icon =
|
|
76
|
-
options.icon ||
|
|
77
|
-
{ info: 'circle-info', success: 'check', warning: 'triangle-exclamation', error: 'skull-crossbones' }[type];
|
|
81
|
+
static prepareOptions(options) {
|
|
82
|
+
const { type } = options;
|
|
78
83
|
|
|
79
|
-
|
|
84
|
+
return {
|
|
80
85
|
role: type === 'error' || type === 'warning' ? 'alert' : 'status',
|
|
81
86
|
'aria-atomic': 'true',
|
|
82
|
-
onPointerPress: e => {
|
|
83
|
-
if (!e.target.closest('button, [role="button"]')) this.destroy();
|
|
84
|
-
},
|
|
85
|
-
state: 'manual',
|
|
86
87
|
...options,
|
|
87
88
|
addClass: [type].concat(options.addClass),
|
|
88
|
-
icon
|
|
89
|
-
|
|
89
|
+
icon:
|
|
90
|
+
options.icon ||
|
|
91
|
+
{ info: 'circle-info', success: 'check', warning: 'triangle-exclamation', error: 'skull-crossbones' }[type],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
build() {
|
|
96
|
+
super.build();
|
|
97
|
+
|
|
98
|
+
this.on({
|
|
99
|
+
targetEvent: 'pointerdown',
|
|
100
|
+
id: 'notifyDismiss',
|
|
101
|
+
callback: e => {
|
|
102
|
+
if (!e.target.closest('button, [role="button"]')) this.destroy();
|
|
103
|
+
},
|
|
104
|
+
});
|
|
95
105
|
}
|
|
96
106
|
}
|
|
@@ -18,19 +18,6 @@ const StyledIcon = styled(
|
|
|
18
18
|
`,
|
|
19
19
|
);
|
|
20
20
|
|
|
21
|
-
const defaultOptions = {
|
|
22
|
-
uniqueId: true,
|
|
23
|
-
state: 'manual',
|
|
24
|
-
outsideClose: false,
|
|
25
|
-
get viewport() {
|
|
26
|
-
return document.documentElement;
|
|
27
|
-
},
|
|
28
|
-
get appendTo() {
|
|
29
|
-
return document.body;
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
const state_enum = Object.freeze(['auto', 'manual']);
|
|
33
|
-
|
|
34
21
|
/**
|
|
35
22
|
* Popover component using native HTML popover API with edge-aware positioning.
|
|
36
23
|
*
|
|
@@ -50,45 +37,63 @@ const state_enum = Object.freeze(['auto', 'manual']);
|
|
|
50
37
|
* @returns {Popover} Popover component instance
|
|
51
38
|
*/
|
|
52
39
|
export default class Popover extends StyledIcon {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
40
|
+
static schema = {
|
|
41
|
+
uniqueId: { default: true },
|
|
42
|
+
state: {
|
|
43
|
+
default: 'manual',
|
|
44
|
+
enum: ['auto', 'manual'],
|
|
45
|
+
set(value) {
|
|
46
|
+
this.elem.popover = value;
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
autoOpen: { default: true },
|
|
50
|
+
// Positioning and dismissal config read from this.options by show()/edgeAwarePlacement()
|
|
51
|
+
outsideClose: { default: false },
|
|
52
|
+
viewport: {
|
|
53
|
+
get default() {
|
|
54
|
+
return document.documentElement;
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
appendTo: {
|
|
58
|
+
get default() {
|
|
59
|
+
return document.body;
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
maxWidth: { default: 264 },
|
|
63
|
+
maxHeight: { default: 132 },
|
|
64
|
+
x: {
|
|
65
|
+
set() {
|
|
66
|
+
this._placeAtPoint();
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
y: {
|
|
70
|
+
set() {
|
|
71
|
+
this._placeAtPoint();
|
|
68
72
|
},
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
},
|
|
74
|
+
};
|
|
71
75
|
|
|
72
|
-
|
|
76
|
+
build() {
|
|
77
|
+
this.on({
|
|
78
|
+
targetEvent: 'connected',
|
|
79
|
+
id: 'popoverAutoOpen',
|
|
80
|
+
callback: () => {
|
|
81
|
+
if (!this.options.autoOpen) return;
|
|
82
|
+
const timeoutId = setTimeout(() => this.show(), 200);
|
|
83
|
+
this.replaceCleanup('autoOpen', () => clearTimeout(timeoutId));
|
|
84
|
+
},
|
|
85
|
+
});
|
|
73
86
|
}
|
|
74
87
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
},
|
|
79
|
-
outsideClose() {},
|
|
80
|
-
viewport() {},
|
|
81
|
-
maxWidth() {},
|
|
82
|
-
maxHeight() {},
|
|
83
|
-
x() {},
|
|
84
|
-
y() {},
|
|
85
|
-
};
|
|
88
|
+
_placeAtPoint() {
|
|
89
|
+
if (this.options.x !== undefined && this.options.y !== undefined) this.edgeAwarePlacement(this.options);
|
|
90
|
+
}
|
|
86
91
|
|
|
87
92
|
edgeAwarePlacement({
|
|
88
93
|
x,
|
|
89
94
|
y,
|
|
90
|
-
maxHeight = this.options.maxHeight
|
|
91
|
-
maxWidth = this.options.maxWidth
|
|
95
|
+
maxHeight = this.options.maxHeight,
|
|
96
|
+
maxWidth = this.options.maxWidth,
|
|
92
97
|
padding = 24,
|
|
93
98
|
viewport = this.options.viewport || this.options.appendTo,
|
|
94
99
|
}) {
|
|
@@ -69,38 +69,42 @@ const RadioButtonInput = styled(
|
|
|
69
69
|
* @returns {RadioButton} RadioButton component instance
|
|
70
70
|
*/
|
|
71
71
|
class RadioButton extends Component {
|
|
72
|
-
static
|
|
73
|
-
options
|
|
74
|
-
|
|
72
|
+
static schema = {
|
|
73
|
+
options: {
|
|
74
|
+
set(value) {
|
|
75
|
+
this.empty();
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
if (!value) return;
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
79
|
+
this.append(
|
|
80
|
+
value.map(
|
|
81
|
+
option =>
|
|
82
|
+
new RadioButtonLabel({
|
|
83
|
+
tag: 'label',
|
|
84
|
+
append: [
|
|
85
|
+
new RadioButtonInput({
|
|
86
|
+
tag: 'input',
|
|
87
|
+
type: 'radio',
|
|
88
|
+
value: option?.value || option,
|
|
89
|
+
name: this.uniqueId,
|
|
90
|
+
checked: this.options.value === (option?.value || option),
|
|
91
|
+
onChange: event => {
|
|
92
|
+
if (event.target.checked) this.options.value = event.target.value;
|
|
93
|
+
},
|
|
94
|
+
}),
|
|
95
|
+
option?.label || option,
|
|
96
|
+
],
|
|
97
|
+
}),
|
|
98
|
+
),
|
|
99
|
+
);
|
|
100
|
+
},
|
|
99
101
|
},
|
|
100
|
-
value
|
|
101
|
-
|
|
102
|
-
input.
|
|
103
|
-
|
|
102
|
+
value: {
|
|
103
|
+
set(value) {
|
|
104
|
+
this.elem.querySelectorAll('input[type="radio"]').forEach(input => {
|
|
105
|
+
input.checked = input.value === String(value);
|
|
106
|
+
});
|
|
107
|
+
},
|
|
104
108
|
},
|
|
105
109
|
};
|
|
106
110
|
}
|
|
@@ -16,20 +16,26 @@ import { routeToRegex } from './utils';
|
|
|
16
16
|
* @returns {Router} Router component instance
|
|
17
17
|
*/
|
|
18
18
|
class Router extends Component {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
// Routing config read from this.options by the path getters and renderView()
|
|
20
|
+
static schema = {
|
|
21
|
+
views: {},
|
|
22
|
+
defaultPath: {},
|
|
23
|
+
notFound: {},
|
|
24
|
+
onRenderView: {},
|
|
25
|
+
mode: { default: 'hash', enum: ['hash', 'history'] },
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
static prepareOptions(options) {
|
|
29
|
+
return {
|
|
30
|
+
defaultPath: Object.keys(options.views || {})[0],
|
|
31
|
+
...options,
|
|
32
|
+
style: {
|
|
33
|
+
display: 'flex',
|
|
34
|
+
flex: 1,
|
|
35
|
+
overflow: 'hidden',
|
|
36
|
+
...options.style,
|
|
30
37
|
},
|
|
31
|
-
|
|
32
|
-
);
|
|
38
|
+
};
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
/**
|
|
@@ -102,14 +108,6 @@ class Router extends Component {
|
|
|
102
108
|
return parameters;
|
|
103
109
|
}
|
|
104
110
|
|
|
105
|
-
static handlers = {
|
|
106
|
-
views() {},
|
|
107
|
-
defaultPath() {},
|
|
108
|
-
notFound() {},
|
|
109
|
-
onRenderView() {},
|
|
110
|
-
mode() {},
|
|
111
|
-
};
|
|
112
|
-
|
|
113
111
|
build() {
|
|
114
112
|
const reRenderView = () => this.renderView();
|
|
115
113
|
|