@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,281 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
|
+
"$id": "JxAccordionItem",
|
|
4
|
+
"tagName": "jx-accordion-item",
|
|
5
|
+
"observedAttributes": ["label", "open", "name", "level"],
|
|
6
|
+
"$elements": [
|
|
7
|
+
{
|
|
8
|
+
"$ref": "./jx-icon.json"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"state": {
|
|
12
|
+
"label": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"default": "",
|
|
15
|
+
"attribute": "label",
|
|
16
|
+
"description": "The section's title, printed in the summary row, and the disclosure control's accessible name — it is written as aria-label on the summary rather than left to name-from-content, because the actions row lives inside the summary and would otherwise be read as part of the section's name (measured in Chrome: \"Typography Clear typography overrides\"). It is not optional: with no label the summary is a control a reader hears as \"collapsed, button\" and nothing else, and no lint asks for it, so the element's own test pins it instead."
|
|
17
|
+
},
|
|
18
|
+
"open": {
|
|
19
|
+
"type": "boolean",
|
|
20
|
+
"default": false,
|
|
21
|
+
"attribute": "open",
|
|
22
|
+
"description": "Whether the section is disclosed. It is a two-way value: the platform writes it when the reader opens the section, and a host may write it to open or close one. Written as a property it does NOT reflect back onto the host's own open attribute, so read it as a property (or from the toggle event) rather than with getAttribute."
|
|
23
|
+
},
|
|
24
|
+
"name": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"default": "",
|
|
27
|
+
"attribute": "name",
|
|
28
|
+
"description": "Forwarded to the inner details as its name, which is how the platform makes a group of sections mutually exclusive: every item carrying the same name closes the others when it opens. Empty means the item is independent, which is what every shipped accordion in Studio wants."
|
|
29
|
+
},
|
|
30
|
+
"level": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"default": "",
|
|
33
|
+
"attribute": "level",
|
|
34
|
+
"description": "Opt in to heading semantics: a number here exposes the section's label as a heading at that level, so a long settings panel can be skimmed by heading navigation. It is a visually hidden [part=\"heading\"] carrying the label, NOT a role on the summary — measured in Chrome, role=heading on a summary REPLACES the disclosure, which loses expandable and the expanded state, and a heading nested inside the summary is pruned out of the tree entirely. The cost of the shape that works is that the label text is announced twice when reading linearly, once as the heading and once as the disclosure; that is the trade, and it is why the prop is opt-in."
|
|
35
|
+
},
|
|
36
|
+
"onToggle": {
|
|
37
|
+
"$prototype": "Function",
|
|
38
|
+
"body": [
|
|
39
|
+
{
|
|
40
|
+
"if": {
|
|
41
|
+
"operator": "!==",
|
|
42
|
+
"target": {
|
|
43
|
+
"$ref": "event#/detail"
|
|
44
|
+
},
|
|
45
|
+
"value": {
|
|
46
|
+
"$ref": "event#/target/open"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"then": [
|
|
50
|
+
{
|
|
51
|
+
"operator": "=",
|
|
52
|
+
"target": {
|
|
53
|
+
"$ref": "#/state/open"
|
|
54
|
+
},
|
|
55
|
+
"value": {
|
|
56
|
+
"$ref": "event#/target/open"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"dispatchEvent": "toggle",
|
|
61
|
+
"detail": {
|
|
62
|
+
"$ref": "#/state/open"
|
|
63
|
+
},
|
|
64
|
+
"bubbles": true
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"emits": [
|
|
70
|
+
{
|
|
71
|
+
"name": "toggle",
|
|
72
|
+
"description": "The section opened or closed; detail is the new open state. The PLATFORM's event name, so a host that already reads e.target.open off a native details toggle changes nothing but the element it listens on — e.target is the inner details element, not the host, and details.open is the state that just changed. It bubbles out of the details as far as the host and stops there (see onHostToggle), so bind it ON the jx-accordion-item rather than on a container."
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
"description": "Mirrors the platform's own toggle into open and re-announces it as an event that reaches the host, because a native toggle does not bubble and would never leave the inner details. The guard is what makes that safe: the re-announcement is dispatched from the same details the handler listens on, so an unguarded body would hear its own event and recurse forever. A toggle whose detail already equals the details' own open state is that echo and is dropped."
|
|
76
|
+
},
|
|
77
|
+
"onHostToggle": {
|
|
78
|
+
"$prototype": "Function",
|
|
79
|
+
"body": [
|
|
80
|
+
{
|
|
81
|
+
"stopPropagation": true
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
"description": "Stops the re-announced toggle at the element's own boundary. The platform's toggle never bubbles, and the kit's overlays rely on that: jx-popover, jx-menu, jx-tooltip and jx-dialog all bind ontoggle on their own root and read event.newState with no target guard, so a toggle arriving from a descendant would be read as the overlay's own. Measured in Chrome before this existed: opening a section inside a shown jx-popover flipped the panel's open to false and dropped its data-open styling while it was still in the top layer. Listeners bound on this element still run — stopPropagation does not stop the other listeners on the node it is called from — so a host's ontoggle on the jx-accordion-item is unaffected; only ancestors stop hearing it."
|
|
85
|
+
},
|
|
86
|
+
"onActions": {
|
|
87
|
+
"$prototype": "Function",
|
|
88
|
+
"body": [
|
|
89
|
+
{
|
|
90
|
+
"stopPropagation": true
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"if": {
|
|
94
|
+
"operator": "===",
|
|
95
|
+
"target": {
|
|
96
|
+
"$ref": "event#/target"
|
|
97
|
+
},
|
|
98
|
+
"value": {
|
|
99
|
+
"$ref": "event#/currentTarget"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"then": [
|
|
103
|
+
{
|
|
104
|
+
"preventDefault": true
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"description": "The actions row sits INSIDE the summary, so that it stays visible while the section is closed — a sibling of summary inside details is hidden by the UA whenever the section is shut. The cost is that a click on the row's own space would also toggle the section, so the row cancels the activation, and a click on the row that reached nothing else toggles nothing: that is the intended trade. It cancels ONLY that click. A slotted control does not need cancelling — it is the click's own activation target, so the summary never toggles for it (measured: a button inside a summary leaves details.open alone) — and cancelling there would kill the control's own default, which is exactly what it did before this guard: a slotted link did not navigate and a popovertarget invoker did not open its popover. The residue is a non-interactive element slotted into the actions row, which still toggles the section; inert marks belong in [slot=\"heading\"], which is what that slot is for."
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"ontoggle": {
|
|
113
|
+
"$ref": "#/state/onHostToggle"
|
|
114
|
+
},
|
|
115
|
+
"style": {
|
|
116
|
+
"display": "block",
|
|
117
|
+
"&[hidden]": {
|
|
118
|
+
"display": "none"
|
|
119
|
+
},
|
|
120
|
+
"fontFamily": "var(--jx-font-sans)",
|
|
121
|
+
"fontSize": "var(--jx-text-md)",
|
|
122
|
+
"lineHeight": "var(--jx-leading-md)",
|
|
123
|
+
"color": "var(--jx-fg)",
|
|
124
|
+
"& > [part=\"heading\"]": {
|
|
125
|
+
"position": "absolute",
|
|
126
|
+
"width": "1px",
|
|
127
|
+
"height": "1px",
|
|
128
|
+
"margin": "-1px",
|
|
129
|
+
"overflow": "hidden",
|
|
130
|
+
"clipPath": "inset(50%)",
|
|
131
|
+
"whiteSpace": "nowrap"
|
|
132
|
+
},
|
|
133
|
+
"& > [part=\"details\"] > [part=\"summary\"]": {
|
|
134
|
+
"display": "flex",
|
|
135
|
+
"alignItems": "center",
|
|
136
|
+
"gap": "var(--jx-space-2)",
|
|
137
|
+
"minHeight": "var(--jx-control-h)",
|
|
138
|
+
"padding": "var(--jx-space-1) var(--jx-space-2)",
|
|
139
|
+
"borderRadius": "var(--jx-radius-sm)",
|
|
140
|
+
"cursor": "default",
|
|
141
|
+
"userSelect": "none",
|
|
142
|
+
"outline": "none",
|
|
143
|
+
"listStyle": "none",
|
|
144
|
+
":hover": {
|
|
145
|
+
"background": "var(--jx-hover-bg)"
|
|
146
|
+
},
|
|
147
|
+
":focus-visible": {
|
|
148
|
+
"outline": "var(--jx-focus-ring)",
|
|
149
|
+
"outlineOffset": "-2px"
|
|
150
|
+
},
|
|
151
|
+
"&::-webkit-details-marker": {
|
|
152
|
+
"display": "none"
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"& > [part=\"details\"] > [part=\"summary\"] > [part=\"marker\"]": {
|
|
156
|
+
"display": "inline-flex",
|
|
157
|
+
"flex": "none",
|
|
158
|
+
"color": "var(--jx-fg-dim)",
|
|
159
|
+
"transition": "transform var(--jx-dur-1) var(--jx-ease-out)"
|
|
160
|
+
},
|
|
161
|
+
"& > [part=\"details\"][open] > [part=\"summary\"] > [part=\"marker\"]": {
|
|
162
|
+
"transform": "rotate(90deg)"
|
|
163
|
+
},
|
|
164
|
+
"& > [part=\"details\"] > [part=\"summary\"] > [part=\"label\"]": {
|
|
165
|
+
"flex": "1",
|
|
166
|
+
"minWidth": "0",
|
|
167
|
+
"overflow": "hidden",
|
|
168
|
+
"textOverflow": "ellipsis",
|
|
169
|
+
"whiteSpace": "nowrap",
|
|
170
|
+
"fontWeight": "500"
|
|
171
|
+
},
|
|
172
|
+
"& > [part=\"details\"] > [part=\"summary\"] > [part=\"actions\"]": {
|
|
173
|
+
"display": "inline-flex",
|
|
174
|
+
"flex": "none",
|
|
175
|
+
"alignItems": "center",
|
|
176
|
+
"gap": "var(--jx-space-1)"
|
|
177
|
+
},
|
|
178
|
+
"& > [part=\"details\"] > [part=\"body\"]": {
|
|
179
|
+
"padding": "var(--jx-space-2)"
|
|
180
|
+
},
|
|
181
|
+
"& > [part=\"details\"] > [part=\"summary\"] > [part=\"actions\"]:empty": {
|
|
182
|
+
"display": "none"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"children": [
|
|
186
|
+
{
|
|
187
|
+
"tagName": "span",
|
|
188
|
+
"attributes": {
|
|
189
|
+
"part": "heading",
|
|
190
|
+
"role": "${state.level ? 'heading' : null}",
|
|
191
|
+
"aria-level": "${state.level || null}",
|
|
192
|
+
"hidden": "${state.level ? null : ''}"
|
|
193
|
+
},
|
|
194
|
+
"textContent": "${state.label}"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"tagName": "details",
|
|
198
|
+
"attributes": {
|
|
199
|
+
"part": "details",
|
|
200
|
+
"open": {
|
|
201
|
+
"$ref": "#/state/open"
|
|
202
|
+
},
|
|
203
|
+
"name": "${state.name || null}"
|
|
204
|
+
},
|
|
205
|
+
"ontoggle": {
|
|
206
|
+
"$ref": "#/state/onToggle"
|
|
207
|
+
},
|
|
208
|
+
"children": [
|
|
209
|
+
{
|
|
210
|
+
"tagName": "summary",
|
|
211
|
+
"attributes": {
|
|
212
|
+
"part": "summary",
|
|
213
|
+
"aria-label": "${state.label || null}"
|
|
214
|
+
},
|
|
215
|
+
"children": [
|
|
216
|
+
{
|
|
217
|
+
"tagName": "span",
|
|
218
|
+
"attributes": {
|
|
219
|
+
"part": "marker",
|
|
220
|
+
"aria-hidden": "true"
|
|
221
|
+
},
|
|
222
|
+
"children": [
|
|
223
|
+
{
|
|
224
|
+
"tagName": "jx-icon",
|
|
225
|
+
"$props": {
|
|
226
|
+
"name": "caret-right",
|
|
227
|
+
"weight": "bold"
|
|
228
|
+
},
|
|
229
|
+
"attributes": {
|
|
230
|
+
"part": "marker-icon"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"tagName": "span",
|
|
237
|
+
"attributes": {
|
|
238
|
+
"part": "label"
|
|
239
|
+
},
|
|
240
|
+
"textContent": "${state.label}"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"tagName": "slot",
|
|
244
|
+
"attributes": {
|
|
245
|
+
"name": "heading"
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"tagName": "span",
|
|
250
|
+
"attributes": {
|
|
251
|
+
"part": "actions"
|
|
252
|
+
},
|
|
253
|
+
"onclick": {
|
|
254
|
+
"$ref": "#/state/onActions"
|
|
255
|
+
},
|
|
256
|
+
"children": [
|
|
257
|
+
{
|
|
258
|
+
"tagName": "slot",
|
|
259
|
+
"attributes": {
|
|
260
|
+
"name": "actions"
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
]
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"tagName": "div",
|
|
269
|
+
"attributes": {
|
|
270
|
+
"part": "body"
|
|
271
|
+
},
|
|
272
|
+
"children": [
|
|
273
|
+
{
|
|
274
|
+
"tagName": "slot"
|
|
275
|
+
}
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
|
+
"$id": "JxAccordion",
|
|
4
|
+
"tagName": "jx-accordion",
|
|
5
|
+
"observedAttributes": ["multiple"],
|
|
6
|
+
"state": {
|
|
7
|
+
"multiple": {
|
|
8
|
+
"type": "boolean",
|
|
9
|
+
"default": true,
|
|
10
|
+
"attribute": "multiple",
|
|
11
|
+
"description": "Whether more than one section may stand open at once, which is what an un-named details already is and what all six shipped Studio panels want. It is ADVISORY: the container declares the intent and reflects it as data-exclusive, and it does NOT enforce it, because the platform's own switch for exclusivity is the name attribute on each details and that attribute belongs to the item. A container that reached into its slotted children to write one would be the foreign-attribute write §2 principle 5 forbids, and there is no declarative channel from a container to light-DOM children it did not author — a slot leaves no node and projects no props. So multiple=\"false\" is a statement a consumer makes true by giving every item the same name; the element is the place that statement is written down and read back, not the place it is imposed. The marker is spelled for the NOTABLE state rather than for the prop: every other boolean reflection in the kit (quiet, compact, checked, disabled, open, loading, stepper, selected, stacked, determinate, destructive, badInput, indeterminate) defaults false and marks attribute-present, so a marker named data-multiple would have been present on every default stack and absent exactly where the intent was declared, and styling the exclusive case would read :not([data-multiple])."
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"attributes": {
|
|
15
|
+
"data-exclusive": "${state.multiple ? null : ''}"
|
|
16
|
+
},
|
|
17
|
+
"style": {
|
|
18
|
+
"display": "flex",
|
|
19
|
+
"&[hidden]": {
|
|
20
|
+
"display": "none"
|
|
21
|
+
},
|
|
22
|
+
"flexDirection": "column",
|
|
23
|
+
"minWidth": "0",
|
|
24
|
+
"& > :not([hidden]) ~ *": {
|
|
25
|
+
"borderBlockStart": "1px solid var(--jx-border)"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"children": [
|
|
29
|
+
{
|
|
30
|
+
"tagName": "slot"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|