@jxsuite/ui 0.0.0 → 0.1.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/components/jx-accordion-item.json +281 -0
- package/components/jx-accordion.json +33 -0
- package/components/jx-action-button.json +261 -33
- package/components/jx-action-group.json +123 -0
- package/components/jx-button.json +133 -25
- package/components/jx-checkbox.json +215 -0
- package/components/jx-color-area.json +263 -0
- package/components/jx-color-field.json +565 -0
- package/components/jx-color-slider.json +216 -0
- package/components/jx-combobox.json +544 -0
- package/components/jx-dialog.json +416 -0
- package/components/jx-divider.json +52 -0
- package/components/jx-dot.json +38 -0
- package/components/jx-field.json +162 -0
- package/components/jx-kbd.json +24 -0
- package/components/jx-listbox.json +76 -0
- package/components/jx-menu-item.json +5 -12
- package/components/jx-menu.json +45 -6
- package/components/jx-number-field.json +441 -0
- package/components/jx-option.json +350 -0
- package/components/jx-popover.json +227 -0
- package/components/jx-select.json +637 -0
- package/components/jx-spinner.json +129 -0
- package/components/jx-split.json +221 -0
- package/components/jx-swatch-group.json +107 -0
- package/components/jx-swatch.json +262 -0
- package/components/jx-switch.json +253 -0
- package/components/jx-tab-panel.json +58 -0
- package/components/jx-tab.json +296 -0
- package/components/jx-tabs.json +124 -0
- package/components/jx-textfield.json +639 -0
- package/components/jx-toast-host.json +121 -0
- package/components/jx-toast.json +255 -0
- package/components/jx-toolbar.json +81 -0
- package/components/jx-tooltip.json +207 -0
- package/components/jx-tree-item.json +325 -0
- package/components/jx-tree.json +202 -0
- package/icons/list.json +4 -0
- package/icons/manifest.json +12 -0
- package/package.json +27 -5
- package/project.json +164 -153
- package/src/behaviors/action-group.ts +255 -0
- package/src/behaviors/color-area.ts +303 -0
- package/src/behaviors/color-field.ts +465 -0
- package/src/behaviors/color-slider.ts +154 -0
- package/src/behaviors/combobox.ts +474 -0
- package/src/behaviors/dialog.ts +137 -0
- package/src/behaviors/listbox.ts +118 -0
- package/src/behaviors/menu.ts +80 -48
- package/src/behaviors/number-field.ts +161 -0
- package/src/behaviors/popover.ts +399 -0
- package/src/behaviors/select.ts +154 -0
- package/src/behaviors/split.ts +478 -0
- package/src/behaviors/swatch-group.ts +297 -0
- package/src/behaviors/tabs.ts +319 -0
- package/src/behaviors/textfield.ts +164 -0
- package/src/behaviors/toast-host.ts +241 -0
- package/src/behaviors/toast.ts +261 -0
- package/src/behaviors/toolbar.ts +413 -0
- package/src/behaviors/tooltip.ts +715 -0
- package/src/behaviors/tree.ts +830 -0
- package/src/color.ts +433 -0
- package/src/documents.ts +91 -1
- package/src/index.ts +41 -1
- package/src/loaders.ts +47 -0
- package/src/testing/anchor-support.ts +28 -0
- package/src/testing/popover-shim.ts +39 -6
- package/src/theme.ts +30 -6
- package/stylebook/jx-accordion-item.json +195 -0
- package/stylebook/jx-accordion.json +220 -0
- package/stylebook/jx-action-button.json +191 -23
- package/stylebook/jx-action-group.json +335 -0
- package/stylebook/jx-button.json +129 -26
- package/stylebook/jx-checkbox.json +245 -0
- package/stylebook/jx-color-area.json +272 -0
- package/stylebook/jx-color-field.json +261 -0
- package/stylebook/jx-color-slider.json +220 -0
- package/stylebook/jx-combobox.json +332 -0
- package/stylebook/jx-dialog.json +186 -0
- package/stylebook/jx-divider.json +125 -0
- package/stylebook/jx-dot.json +92 -0
- package/stylebook/jx-field.json +313 -0
- package/stylebook/jx-icon.json +4 -0
- package/stylebook/jx-kbd.json +90 -0
- package/stylebook/jx-listbox.json +337 -0
- package/stylebook/jx-menu.json +0 -1
- package/stylebook/jx-number-field.json +203 -0
- package/stylebook/jx-option.json +285 -0
- package/stylebook/jx-popover.json +123 -0
- package/stylebook/jx-select.json +407 -0
- package/stylebook/jx-spinner.json +111 -0
- package/stylebook/jx-split.json +170 -0
- package/stylebook/jx-swatch-group.json +175 -0
- package/stylebook/jx-swatch.json +249 -0
- package/stylebook/jx-switch.json +240 -0
- package/stylebook/jx-tab-panel.json +147 -0
- package/stylebook/jx-tab.json +201 -0
- package/stylebook/jx-tabs.json +278 -0
- package/stylebook/jx-textfield.json +309 -0
- package/stylebook/jx-toast-host.json +157 -0
- package/stylebook/jx-toast.json +266 -0
- package/stylebook/jx-toolbar.json +435 -0
- package/stylebook/jx-tooltip.json +162 -0
- package/stylebook/jx-tree-item.json +258 -0
- package/stylebook/jx-tree.json +429 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
|
+
"$id": "JxListbox",
|
|
4
|
+
"tagName": "jx-listbox",
|
|
5
|
+
"observedAttributes": ["label", "labelledby", "active"],
|
|
6
|
+
"state": {
|
|
7
|
+
"label": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"default": "",
|
|
10
|
+
"attribute": "label",
|
|
11
|
+
"description": "The list's accessible name, forwarded as aria-label. REQUIRED unless labelledby names a visible heading: listbox takes its name from a label rather than from its rows, so an unnamed one is announced as \"listbox\" and nothing else. Nothing lints it — a bound role makes the naming rules stand down — so the element's own test is what holds it."
|
|
12
|
+
},
|
|
13
|
+
"labelledby": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"default": "",
|
|
16
|
+
"attribute": "labelledby",
|
|
17
|
+
"description": "Forwarded as aria-labelledby, naming the element that already says what this list is."
|
|
18
|
+
},
|
|
19
|
+
"active": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"default": "",
|
|
22
|
+
"attribute": "active",
|
|
23
|
+
"description": "The ID of the row the caret is on; the empty string when none is. THIS IS THE ONE STRING A CONSUMER WRITES: the same id its owning field points aria-activedescendant at, so the field and the row are told the same thing once instead of the question being re-decided per row. The sidecar turns it into each row's selected and scrolls the new one back into view."
|
|
24
|
+
},
|
|
25
|
+
"onMount": {
|
|
26
|
+
"$prototype": "Function",
|
|
27
|
+
"$src": "jx-ui:/behaviors/listbox.ts",
|
|
28
|
+
"$export": "mountListbox",
|
|
29
|
+
"description": "Keeps every row's selected in step with active for as long as the element lives, and scrolls the active row into view. Both are things a document body cannot say: the flag lives on a foreign element, and scrolling is a measurement."
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"attributes": {
|
|
33
|
+
"role": "listbox",
|
|
34
|
+
"aria-label": "${state.label || null}",
|
|
35
|
+
"aria-labelledby": "${state.labelledby || null}",
|
|
36
|
+
"data-active": "${state.active}"
|
|
37
|
+
},
|
|
38
|
+
"style": {
|
|
39
|
+
"$description": "There is deliberately NO tabindex here, and no rule that draws a focus ring: the element never takes DOM focus. One of its two owners is a field that must keep the caret, and the other is nothing at all — a panel filtering for a caret in another realm. A listbox that is operated from somewhere else is exactly the shape ARIA's aria-activedescendant exists for.",
|
|
40
|
+
"display": "block",
|
|
41
|
+
"&[hidden]": {
|
|
42
|
+
"display": "none"
|
|
43
|
+
},
|
|
44
|
+
"boxSizing": "border-box",
|
|
45
|
+
"minHeight": "0",
|
|
46
|
+
"maxBlockSize": "var(--jx-listbox-max-block-size, none)",
|
|
47
|
+
"overflowY": "auto",
|
|
48
|
+
"margin": "0",
|
|
49
|
+
"padding": "0",
|
|
50
|
+
"color": "var(--jx-fg)",
|
|
51
|
+
"fontFamily": "var(--jx-font-sans)",
|
|
52
|
+
"fontSize": "var(--jx-text-md)",
|
|
53
|
+
"lineHeight": "var(--jx-leading-md)",
|
|
54
|
+
"& [part=\"group-heading\"]": {
|
|
55
|
+
"$description": "A furniture part a CONSUMER writes, styled from here because this is the definition that owns the box it sits in (ui.md 3.1). A grouped list is a role=\"group\" wrapper holding a heading and its rows — the formula palette's shape — and in a light DOM the container's own rule reaches it without a class, which is the whole point of the cascade being one.",
|
|
56
|
+
"display": "block",
|
|
57
|
+
"padding": "var(--jx-space-3) var(--jx-space-3) var(--jx-space-1)",
|
|
58
|
+
"fontSize": "var(--jx-text-xs)",
|
|
59
|
+
"textTransform": "uppercase",
|
|
60
|
+
"letterSpacing": "0.5px",
|
|
61
|
+
"color": "var(--jx-fg-muted)"
|
|
62
|
+
},
|
|
63
|
+
"& [part=\"empty\"]": {
|
|
64
|
+
"$description": "The other furniture part: the sentence a consumer draws when its own filter matched nothing. What that sentence SAYS belongs to the surface — \"No matches\", \"Nothing here yet\", a hint about the mode — so the element draws it and never writes it.",
|
|
65
|
+
"display": "block",
|
|
66
|
+
"padding": "var(--jx-space-4) var(--jx-space-3)",
|
|
67
|
+
"textAlign": "center",
|
|
68
|
+
"color": "var(--jx-fg-muted)"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"children": [
|
|
72
|
+
{
|
|
73
|
+
"tagName": "slot"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
@@ -175,8 +175,7 @@
|
|
|
175
175
|
{
|
|
176
176
|
"tagName": "slot",
|
|
177
177
|
"attributes": {
|
|
178
|
-
"name": "icon"
|
|
179
|
-
"part": "icon-slot"
|
|
178
|
+
"name": "icon"
|
|
180
179
|
}
|
|
181
180
|
}
|
|
182
181
|
]
|
|
@@ -194,10 +193,7 @@
|
|
|
194
193
|
},
|
|
195
194
|
"children": [
|
|
196
195
|
{
|
|
197
|
-
"tagName": "slot"
|
|
198
|
-
"attributes": {
|
|
199
|
-
"part": "label-slot"
|
|
200
|
-
}
|
|
196
|
+
"tagName": "slot"
|
|
201
197
|
}
|
|
202
198
|
]
|
|
203
199
|
},
|
|
@@ -210,8 +206,7 @@
|
|
|
210
206
|
{
|
|
211
207
|
"tagName": "slot",
|
|
212
208
|
"attributes": {
|
|
213
|
-
"name": "description"
|
|
214
|
-
"part": "description-slot"
|
|
209
|
+
"name": "description"
|
|
215
210
|
}
|
|
216
211
|
}
|
|
217
212
|
]
|
|
@@ -227,8 +222,7 @@
|
|
|
227
222
|
{
|
|
228
223
|
"tagName": "slot",
|
|
229
224
|
"attributes": {
|
|
230
|
-
"name": "value"
|
|
231
|
-
"part": "value-slot"
|
|
225
|
+
"name": "value"
|
|
232
226
|
}
|
|
233
227
|
}
|
|
234
228
|
]
|
|
@@ -257,8 +251,7 @@
|
|
|
257
251
|
{
|
|
258
252
|
"tagName": "slot",
|
|
259
253
|
"attributes": {
|
|
260
|
-
"name": "submenu"
|
|
261
|
-
"part": "submenu-slot"
|
|
254
|
+
"name": "submenu"
|
|
262
255
|
}
|
|
263
256
|
}
|
|
264
257
|
]
|
package/components/jx-menu.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
3
|
"$id": "JxMenu",
|
|
4
4
|
"tagName": "jx-menu",
|
|
5
|
-
"observedAttributes": ["label", "x", "y", "floor"],
|
|
5
|
+
"observedAttributes": ["label", "placement", "x", "y", "floor"],
|
|
6
6
|
"state": {
|
|
7
7
|
"label": {
|
|
8
8
|
"type": "string",
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
"attribute": "label",
|
|
11
11
|
"description": "The accessible name of the menu."
|
|
12
12
|
},
|
|
13
|
+
"placement": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"default": "",
|
|
16
|
+
"attribute": "placement",
|
|
17
|
+
"description": "Where the menu sits relative to the element it was opened from, as a CSS position-area value, or empty. Empty is the default and means placement by x and y, because a menu's usual opening is at a POINTER — a context menu — where the source it was shown from is what gets the keyboard back and not where the panel hangs. A menu that hangs from a button sets it (block-end span-inline-end, below and leading-aligned; block-end span-inline-start for a trailing edge) and is then placed by the platform against that button, followed through scroll and resize, and flipped when it would overflow; a submenu is placed inline-end span-block-end of its row without being asked. The value is passed to the property as written. A stack with a floor is never anchored: a floor is a limit the platform's fallbacks cannot express, so it keeps the coordinate placement the clamp honours."
|
|
18
|
+
},
|
|
13
19
|
"x": {
|
|
14
20
|
"type": "number",
|
|
15
21
|
"default": 0,
|
|
@@ -28,6 +34,16 @@
|
|
|
28
34
|
"attribute": "floor",
|
|
29
35
|
"description": "The lowest edge this panel and its submenus may reach, in viewport pixels; 0 means the viewport. A menu opened from a rail that abuts a status bar sets it to the rail's bottom, so a tall submenu never runs down over the bar."
|
|
30
36
|
},
|
|
37
|
+
"anchored": {
|
|
38
|
+
"type": "boolean",
|
|
39
|
+
"default": false,
|
|
40
|
+
"description": "Whether this panel is placed by the platform against the element it was shown from: an opening with a source, an area to use (placement, or the submenu default), and no floor on the stack's root. Written by the behaviour on beforetoggle, before layout, so the first frame is already in place; cleared on close; mirrored as data-anchored for the anchored rule. Not an attribute, because it is the platform's fact."
|
|
41
|
+
},
|
|
42
|
+
"area": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"default": "",
|
|
45
|
+
"description": "The position-area the anchored rule reads: placement when it is set, else the submenu default for a menu inside a row, else empty. Derived by the behaviour on beforetoggle rather than by the document, because only the behaviour can see whether this menu is a submenu."
|
|
46
|
+
},
|
|
31
47
|
"open": {
|
|
32
48
|
"type": "boolean",
|
|
33
49
|
"default": false,
|
|
@@ -39,6 +55,12 @@
|
|
|
39
55
|
"$export": "onMenuKeydown",
|
|
40
56
|
"description": "The menu keyboard contract: Arrow keys, Home, End and typeahead move; Enter and Space activate; ArrowRight opens a submenu and ArrowLeft leaves it; Escape closes one level; Tab closes the whole stack."
|
|
41
57
|
},
|
|
58
|
+
"onBeforeToggle": {
|
|
59
|
+
"$prototype": "Function",
|
|
60
|
+
"$src": "jx-ui:/behaviors/menu.ts",
|
|
61
|
+
"$export": "onMenuBeforeToggle",
|
|
62
|
+
"description": "Decides anchored and area before the panel is laid out (see the two)."
|
|
63
|
+
},
|
|
42
64
|
"onToggle": {
|
|
43
65
|
"$prototype": "Function",
|
|
44
66
|
"$src": "jx-ui:/behaviors/menu.ts",
|
|
@@ -66,11 +88,15 @@
|
|
|
66
88
|
"role": "menu",
|
|
67
89
|
"aria-label": "${state.label}",
|
|
68
90
|
"popover": "auto",
|
|
69
|
-
"tabindex": "-1"
|
|
91
|
+
"tabindex": "-1",
|
|
92
|
+
"data-anchored": "${state.anchored ? '' : null}"
|
|
70
93
|
},
|
|
71
94
|
"onkeydown": {
|
|
72
95
|
"$ref": "#/state/onKeydown"
|
|
73
96
|
},
|
|
97
|
+
"onbeforetoggle": {
|
|
98
|
+
"$ref": "#/state/onBeforeToggle"
|
|
99
|
+
},
|
|
74
100
|
"ontoggle": {
|
|
75
101
|
"$ref": "#/state/onToggle"
|
|
76
102
|
},
|
|
@@ -78,6 +104,10 @@
|
|
|
78
104
|
"$ref": "#/state/onPointerOver"
|
|
79
105
|
},
|
|
80
106
|
"style": {
|
|
107
|
+
"display": "revert-layer",
|
|
108
|
+
"&[hidden]": {
|
|
109
|
+
"display": "none"
|
|
110
|
+
},
|
|
81
111
|
"position": "fixed",
|
|
82
112
|
"insetInlineStart": "${state.x}px",
|
|
83
113
|
"insetBlockStart": "${state.y}px",
|
|
@@ -105,6 +135,18 @@
|
|
|
105
135
|
":popover-open": {
|
|
106
136
|
"display": "flex"
|
|
107
137
|
},
|
|
138
|
+
"&[hidden]:popover-open": {
|
|
139
|
+
"display": "none"
|
|
140
|
+
},
|
|
141
|
+
"@supports (position-area: block-end)": {
|
|
142
|
+
"$description": "The anchored placement, for a menu that hangs from a button and for every submenu: the platform puts it against its IMPLICIT anchor — the element it was shown from — follows that element through scroll and resize, and flips it when the first placement would overflow, which for a submenu is the flip to its parent's inline-start the clamp used to compute by hand. No anchor-name is involved; a popover's invoker is its implicit anchor by the platform's own rule (ui.md 5.2, 6). The insets are released so x and y stop mattering. Outside this block, and for a menu at a pointer or on a stack with a floor, the coordinate placement above is the answer, unchanged.",
|
|
143
|
+
"&[data-anchored]": {
|
|
144
|
+
"insetInlineStart": "auto",
|
|
145
|
+
"insetBlockStart": "auto",
|
|
146
|
+
"positionArea": "${state.area}",
|
|
147
|
+
"positionTryFallbacks": "flip-block, flip-inline, flip-block flip-inline"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
108
150
|
"& hr": {
|
|
109
151
|
"border": "0",
|
|
110
152
|
"borderTop": "1px solid var(--jx-border)",
|
|
@@ -113,10 +155,7 @@
|
|
|
113
155
|
},
|
|
114
156
|
"children": [
|
|
115
157
|
{
|
|
116
|
-
"tagName": "slot"
|
|
117
|
-
"attributes": {
|
|
118
|
-
"part": "items"
|
|
119
|
-
}
|
|
158
|
+
"tagName": "slot"
|
|
120
159
|
}
|
|
121
160
|
]
|
|
122
161
|
}
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
|
+
"$id": "JxNumberField",
|
|
4
|
+
"tagName": "jx-number-field",
|
|
5
|
+
"$elements": [
|
|
6
|
+
{
|
|
7
|
+
"$ref": "./jx-icon.json"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"observedAttributes": [
|
|
11
|
+
"value",
|
|
12
|
+
"min",
|
|
13
|
+
"max",
|
|
14
|
+
"step",
|
|
15
|
+
"placeholder",
|
|
16
|
+
"label",
|
|
17
|
+
"labelledby",
|
|
18
|
+
"describedby",
|
|
19
|
+
"disabled",
|
|
20
|
+
"stepper",
|
|
21
|
+
"step-up-label",
|
|
22
|
+
"step-down-label",
|
|
23
|
+
"name",
|
|
24
|
+
"size"
|
|
25
|
+
],
|
|
26
|
+
"state": {
|
|
27
|
+
"value": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"default": "",
|
|
30
|
+
"attribute": "value",
|
|
31
|
+
"description": "The field's text, as a string rather than a number. An empty value means empty: a numeric entry would read a removed attribute as 0, so clearing a numeric key would write 0 into the document instead of deleting it. It is bound twice, as the control's value property AND as its value content attribute: the property is what tracks state once the reader has typed (typing sets the control's dirty value flag, after which the attribute no longer moves the live value), and the attribute keeps the control's DEFAULT value equal to its current one. The price of that mirror is that form.reset() is a no-op here, and it is deliberate: the element is not form-associated (specs/ui.md §3.2), so it never hears the reset, and an unmirrored default would move the control while leaving this state where it was — the element and its control disagreeing silently, which is worse than a reset that does nothing."
|
|
32
|
+
},
|
|
33
|
+
"min": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"default": "",
|
|
36
|
+
"attribute": "min",
|
|
37
|
+
"description": "The smallest value the control accepts, as a string. Empty removes the attribute rather than setting an empty one, and the step grid is measured from it."
|
|
38
|
+
},
|
|
39
|
+
"max": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"default": "",
|
|
42
|
+
"attribute": "max",
|
|
43
|
+
"description": "The largest value the control accepts, as a string. Empty removes the attribute."
|
|
44
|
+
},
|
|
45
|
+
"step": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"default": "",
|
|
48
|
+
"attribute": "step",
|
|
49
|
+
"description": "The stepping interval, as a string. Empty removes the attribute, leaving the platform's default of 1."
|
|
50
|
+
},
|
|
51
|
+
"placeholder": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"default": "",
|
|
54
|
+
"attribute": "placeholder",
|
|
55
|
+
"description": "Shown while the field is empty. Not a label."
|
|
56
|
+
},
|
|
57
|
+
"label": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"default": "",
|
|
60
|
+
"attribute": "label",
|
|
61
|
+
"description": "The accessible name, forwarded to the control as aria-label. Required unless a visible label points at the control."
|
|
62
|
+
},
|
|
63
|
+
"labelledby": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"default": "",
|
|
66
|
+
"attribute": "labelledby",
|
|
67
|
+
"description": "Forwarded to the inner control as aria-labelledby."
|
|
68
|
+
},
|
|
69
|
+
"describedby": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"default": "",
|
|
72
|
+
"attribute": "describedby",
|
|
73
|
+
"description": "Forwarded to the inner control as aria-describedby. The help sentence under a row is the row's, not the field's."
|
|
74
|
+
},
|
|
75
|
+
"disabled": {
|
|
76
|
+
"type": "boolean",
|
|
77
|
+
"default": false,
|
|
78
|
+
"attribute": "disabled",
|
|
79
|
+
"description": "Cannot be edited, stepped or focused."
|
|
80
|
+
},
|
|
81
|
+
"stepper": {
|
|
82
|
+
"type": "boolean",
|
|
83
|
+
"default": false,
|
|
84
|
+
"attribute": "stepper",
|
|
85
|
+
"description": "Draw the two stepping buttons. The Arrow keys step whether or not they are drawn; the buttons are for a pointer."
|
|
86
|
+
},
|
|
87
|
+
"stepUpLabel": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"default": "Increase",
|
|
90
|
+
"attribute": "step-up-label",
|
|
91
|
+
"description": "The step-up button's accessible name. It is a real name rather than aria-hidden: a button with no name is reported as unnamed whether or not it is hidden from assistive technology."
|
|
92
|
+
},
|
|
93
|
+
"stepDownLabel": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"default": "Decrease",
|
|
96
|
+
"attribute": "step-down-label",
|
|
97
|
+
"description": "The step-down button's accessible name."
|
|
98
|
+
},
|
|
99
|
+
"name": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"default": "",
|
|
102
|
+
"attribute": "name",
|
|
103
|
+
"description": "The form field name, forwarded to the control."
|
|
104
|
+
},
|
|
105
|
+
"size": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"default": "md",
|
|
108
|
+
"attribute": "size",
|
|
109
|
+
"description": "sm, md or lg. The control height is the kit's, so a row of controls lines up."
|
|
110
|
+
},
|
|
111
|
+
"badInput": {
|
|
112
|
+
"type": "boolean",
|
|
113
|
+
"default": false,
|
|
114
|
+
"description": "Mirrored from the control, never authored: the reader has typed something that is not a number, so the sanitized value reads empty while an edit is still in progress. A host that deletes a key on an empty value must not delete on this one, and it reads the case off the ELEMENT rather than off an event — this prop, or the data-bad-input attribute it mirrors, reached from a handler as event.target.closest('jx-number-field')."
|
|
115
|
+
},
|
|
116
|
+
"onInput": {
|
|
117
|
+
"$prototype": "Function",
|
|
118
|
+
"body": [
|
|
119
|
+
{
|
|
120
|
+
"operator": "=",
|
|
121
|
+
"target": {
|
|
122
|
+
"$ref": "#/state/value"
|
|
123
|
+
},
|
|
124
|
+
"value": {
|
|
125
|
+
"$ref": "event#/target/value"
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"operator": "=",
|
|
130
|
+
"target": {
|
|
131
|
+
"$ref": "#/state/badInput"
|
|
132
|
+
},
|
|
133
|
+
"value": {
|
|
134
|
+
"$ref": "event#/target/validity/badInput"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"description": "Mirrors what the reader types, and whether the control could parse it. The platform's own input event is left alone and goes on bubbling from the control, so a host's event.target is the live input."
|
|
139
|
+
},
|
|
140
|
+
"onChange": {
|
|
141
|
+
"$prototype": "Function",
|
|
142
|
+
"$src": "jx-ui:/behaviors/number-field.ts",
|
|
143
|
+
"$export": "onNumberChange",
|
|
144
|
+
"description": "The reader committed an edit: reads the control back into state. The platform's own change event is neither stopped nor re-sent, so a host still reaches event.target.valueAsNumber (NaN when empty), .validity and .form on the live control; the sanitization case is read off the element as badInput, not off a detail."
|
|
145
|
+
},
|
|
146
|
+
"onKeydown": {
|
|
147
|
+
"$prototype": "Function",
|
|
148
|
+
"$src": "jx-ui:/behaviors/number-field.ts",
|
|
149
|
+
"$export": "onNumberKeydown",
|
|
150
|
+
"description": "Shift and an Arrow move ten steps, through the control's own stepping API.",
|
|
151
|
+
"emits": [
|
|
152
|
+
{
|
|
153
|
+
"name": "input",
|
|
154
|
+
"description": "The value moved. Dispatched from the element, because the platform fires nothing for a value the element wrote itself. No detail: event.target is the element, whose own value is the same string."
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"name": "change",
|
|
158
|
+
"description": "The value was committed. Dispatched from the element for the same reason, with no detail; the sanitization case is the element's own badInput."
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
"onStepUp": {
|
|
163
|
+
"$prototype": "Function",
|
|
164
|
+
"$src": "jx-ui:/behaviors/number-field.ts",
|
|
165
|
+
"$export": "onStepUp",
|
|
166
|
+
"description": "The step-up button: one step up.",
|
|
167
|
+
"emits": [
|
|
168
|
+
{
|
|
169
|
+
"name": "input",
|
|
170
|
+
"description": "The value moved. Dispatched from the element, because the platform fires nothing for a value the element wrote itself. No detail: event.target is the element, whose own value is the same string."
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"name": "change",
|
|
174
|
+
"description": "The value was committed. Dispatched from the element for the same reason, with no detail; the sanitization case is the element's own badInput."
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
"onStepDown": {
|
|
179
|
+
"$prototype": "Function",
|
|
180
|
+
"$src": "jx-ui:/behaviors/number-field.ts",
|
|
181
|
+
"$export": "onStepDown",
|
|
182
|
+
"description": "The step-down button: one step down.",
|
|
183
|
+
"emits": [
|
|
184
|
+
{
|
|
185
|
+
"name": "input",
|
|
186
|
+
"description": "The value moved. Dispatched from the element, because the platform fires nothing for a value the element wrote itself. No detail: event.target is the element, whose own value is the same string."
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"name": "change",
|
|
190
|
+
"description": "The value was committed. Dispatched from the element for the same reason, with no detail; the sanitization case is the element's own badInput."
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
},
|
|
194
|
+
"onStepperPointerDown": {
|
|
195
|
+
"$prototype": "Function",
|
|
196
|
+
"body": [
|
|
197
|
+
{
|
|
198
|
+
"preventDefault": true
|
|
199
|
+
}
|
|
200
|
+
],
|
|
201
|
+
"description": "Keeps focus in the field while a stepping button is pressed. Without it the blur that follows the press fires a second change for the same edit."
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
"attributes": {
|
|
205
|
+
"data-size": "${state.size}",
|
|
206
|
+
"data-disabled": "${state.disabled ? '' : null}",
|
|
207
|
+
"data-stepper": "${state.stepper ? '' : null}",
|
|
208
|
+
"data-bad-input": "${state.badInput ? '' : null}"
|
|
209
|
+
},
|
|
210
|
+
"style": {
|
|
211
|
+
"display": "inline-flex",
|
|
212
|
+
"verticalAlign": "middle",
|
|
213
|
+
"minWidth": "0",
|
|
214
|
+
"&[hidden]": {
|
|
215
|
+
"display": "none"
|
|
216
|
+
},
|
|
217
|
+
"& [part=\"field\"]": {
|
|
218
|
+
"display": "flex",
|
|
219
|
+
"alignItems": "stretch",
|
|
220
|
+
"minWidth": "0",
|
|
221
|
+
"width": "100%"
|
|
222
|
+
},
|
|
223
|
+
"& [part=\"input\"]": {
|
|
224
|
+
"appearance": "none",
|
|
225
|
+
"boxSizing": "border-box",
|
|
226
|
+
"flex": "1 1 auto",
|
|
227
|
+
"width": "100%",
|
|
228
|
+
"minWidth": "0",
|
|
229
|
+
"minHeight": "var(--jx-control-h)",
|
|
230
|
+
"margin": "0",
|
|
231
|
+
"padding": "0 var(--jx-space-3)",
|
|
232
|
+
"border": "1px solid var(--jx-border-strong)",
|
|
233
|
+
"borderRadius": "var(--jx-radius-sm)",
|
|
234
|
+
"background": "var(--jx-bg-input)",
|
|
235
|
+
"color": "var(--jx-fg)",
|
|
236
|
+
"font": "inherit",
|
|
237
|
+
"fontFamily": "var(--jx-font-sans)",
|
|
238
|
+
"fontSize": "var(--jx-text-md)",
|
|
239
|
+
"lineHeight": "var(--jx-leading-md)",
|
|
240
|
+
"fontVariantNumeric": "tabular-nums",
|
|
241
|
+
"outline": "none",
|
|
242
|
+
"transition": "border-color var(--jx-dur-1) var(--jx-ease-out)",
|
|
243
|
+
"::placeholder": {
|
|
244
|
+
"color": "var(--jx-fg-muted)"
|
|
245
|
+
},
|
|
246
|
+
"::-webkit-inner-spin-button": {
|
|
247
|
+
"appearance": "none",
|
|
248
|
+
"margin": "0"
|
|
249
|
+
},
|
|
250
|
+
"::-webkit-outer-spin-button": {
|
|
251
|
+
"appearance": "none",
|
|
252
|
+
"margin": "0"
|
|
253
|
+
},
|
|
254
|
+
":hover": {
|
|
255
|
+
"borderColor": "var(--jx-fg-muted)"
|
|
256
|
+
},
|
|
257
|
+
":focus-visible": {
|
|
258
|
+
"outline": "var(--jx-focus-ring)",
|
|
259
|
+
"outlineOffset": "-1px"
|
|
260
|
+
},
|
|
261
|
+
":disabled": {
|
|
262
|
+
"opacity": "0.5",
|
|
263
|
+
"cursor": "default"
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
"& [part=\"stepper-slot\"]": {
|
|
267
|
+
"display": "contents"
|
|
268
|
+
},
|
|
269
|
+
"& [part=\"stepper\"]": {
|
|
270
|
+
"display": "flex",
|
|
271
|
+
"flexDirection": "column",
|
|
272
|
+
"marginInlineStart": "var(--jx-space-1)"
|
|
273
|
+
},
|
|
274
|
+
"& [part=\"step-up\"], & [part=\"step-down\"]": {
|
|
275
|
+
"appearance": "none",
|
|
276
|
+
"display": "inline-flex",
|
|
277
|
+
"alignItems": "center",
|
|
278
|
+
"justifyContent": "center",
|
|
279
|
+
"flex": "1 1 0",
|
|
280
|
+
"width": "var(--jx-space-5)",
|
|
281
|
+
"padding": "0",
|
|
282
|
+
"margin": "0",
|
|
283
|
+
"border": "1px solid var(--jx-border-strong)",
|
|
284
|
+
"background": "var(--jx-bg-input)",
|
|
285
|
+
"color": "var(--jx-fg-dim)",
|
|
286
|
+
"cursor": "default",
|
|
287
|
+
"--jx-icon-size": "10px",
|
|
288
|
+
":hover": {
|
|
289
|
+
"background": "var(--jx-hover-bg)",
|
|
290
|
+
"color": "var(--jx-fg)"
|
|
291
|
+
},
|
|
292
|
+
":focus-visible": {
|
|
293
|
+
"outline": "var(--jx-focus-ring)",
|
|
294
|
+
"outlineOffset": "-1px"
|
|
295
|
+
},
|
|
296
|
+
":disabled": {
|
|
297
|
+
"opacity": "0.5"
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
"& [part=\"step-up\"]": {
|
|
301
|
+
"borderRadius": "var(--jx-radius-sm) var(--jx-radius-sm) 0 0",
|
|
302
|
+
"borderBottom": "0"
|
|
303
|
+
},
|
|
304
|
+
"& [part=\"step-down\"]": {
|
|
305
|
+
"borderRadius": "0 0 var(--jx-radius-sm) var(--jx-radius-sm)"
|
|
306
|
+
},
|
|
307
|
+
"&[data-size=\"sm\"] [part=\"input\"]": {
|
|
308
|
+
"minHeight": "calc(var(--jx-control-h) - 4px)",
|
|
309
|
+
"fontSize": "var(--jx-text-sm)",
|
|
310
|
+
"padding": "0 var(--jx-space-2)"
|
|
311
|
+
},
|
|
312
|
+
"&[data-size=\"lg\"] [part=\"input\"]": {
|
|
313
|
+
"minHeight": "calc(var(--jx-control-h) + 8px)",
|
|
314
|
+
"fontSize": "var(--jx-text-lg)"
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
"children": [
|
|
318
|
+
{
|
|
319
|
+
"tagName": "div",
|
|
320
|
+
"attributes": {
|
|
321
|
+
"part": "field",
|
|
322
|
+
"role": "none"
|
|
323
|
+
},
|
|
324
|
+
"children": [
|
|
325
|
+
{
|
|
326
|
+
"tagName": "input",
|
|
327
|
+
"attributes": {
|
|
328
|
+
"part": "input",
|
|
329
|
+
"type": "number",
|
|
330
|
+
"inputmode": "decimal",
|
|
331
|
+
"placeholder": "${state.placeholder || null}",
|
|
332
|
+
"aria-label": "${state.label || null}",
|
|
333
|
+
"aria-labelledby": "${state.labelledby || null}",
|
|
334
|
+
"aria-describedby": "${state.describedby || null}",
|
|
335
|
+
"name": "${state.name || null}",
|
|
336
|
+
"min": "${state.min || null}",
|
|
337
|
+
"max": "${state.max || null}",
|
|
338
|
+
"step": "${state.step || null}",
|
|
339
|
+
"disabled": {
|
|
340
|
+
"$ref": "#/state/disabled"
|
|
341
|
+
},
|
|
342
|
+
"value": "${state.value}"
|
|
343
|
+
},
|
|
344
|
+
"value": {
|
|
345
|
+
"$ref": "#/state/value"
|
|
346
|
+
},
|
|
347
|
+
"oninput": {
|
|
348
|
+
"$ref": "#/state/onInput"
|
|
349
|
+
},
|
|
350
|
+
"onchange": {
|
|
351
|
+
"$ref": "#/state/onChange"
|
|
352
|
+
},
|
|
353
|
+
"onkeydown": {
|
|
354
|
+
"$ref": "#/state/onKeydown"
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"tagName": "div",
|
|
359
|
+
"attributes": {
|
|
360
|
+
"part": "stepper-slot",
|
|
361
|
+
"role": "none"
|
|
362
|
+
},
|
|
363
|
+
"$switch": {
|
|
364
|
+
"$ref": "#/state/stepper"
|
|
365
|
+
},
|
|
366
|
+
"cases": {
|
|
367
|
+
"true": {
|
|
368
|
+
"tagName": "div",
|
|
369
|
+
"attributes": {
|
|
370
|
+
"part": "stepper",
|
|
371
|
+
"role": "none"
|
|
372
|
+
},
|
|
373
|
+
"children": [
|
|
374
|
+
{
|
|
375
|
+
"tagName": "button",
|
|
376
|
+
"attributes": {
|
|
377
|
+
"part": "step-up",
|
|
378
|
+
"type": "button",
|
|
379
|
+
"tabindex": "-1",
|
|
380
|
+
"aria-label": "${state.stepUpLabel}",
|
|
381
|
+
"disabled": {
|
|
382
|
+
"$ref": "#/state/disabled"
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
"onclick": {
|
|
386
|
+
"$ref": "#/state/onStepUp"
|
|
387
|
+
},
|
|
388
|
+
"onpointerdown": {
|
|
389
|
+
"$ref": "#/state/onStepperPointerDown"
|
|
390
|
+
},
|
|
391
|
+
"children": [
|
|
392
|
+
{
|
|
393
|
+
"tagName": "jx-icon",
|
|
394
|
+
"$props": {
|
|
395
|
+
"name": "caret-up",
|
|
396
|
+
"weight": "bold"
|
|
397
|
+
},
|
|
398
|
+
"attributes": {
|
|
399
|
+
"part": "step-up-icon"
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
]
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
"tagName": "button",
|
|
406
|
+
"attributes": {
|
|
407
|
+
"part": "step-down",
|
|
408
|
+
"type": "button",
|
|
409
|
+
"tabindex": "-1",
|
|
410
|
+
"aria-label": "${state.stepDownLabel}",
|
|
411
|
+
"disabled": {
|
|
412
|
+
"$ref": "#/state/disabled"
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
"onclick": {
|
|
416
|
+
"$ref": "#/state/onStepDown"
|
|
417
|
+
},
|
|
418
|
+
"onpointerdown": {
|
|
419
|
+
"$ref": "#/state/onStepperPointerDown"
|
|
420
|
+
},
|
|
421
|
+
"children": [
|
|
422
|
+
{
|
|
423
|
+
"tagName": "jx-icon",
|
|
424
|
+
"$props": {
|
|
425
|
+
"name": "caret-down",
|
|
426
|
+
"weight": "bold"
|
|
427
|
+
},
|
|
428
|
+
"attributes": {
|
|
429
|
+
"part": "step-down-icon"
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
]
|
|
433
|
+
}
|
|
434
|
+
]
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
]
|
|
439
|
+
}
|
|
440
|
+
]
|
|
441
|
+
}
|