@astryxdesign/core 0.2.0-canary.9b566f3 → 0.2.0-canary.a714ba9
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/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +40 -1
- package/dist/SelectableCard/SelectableCard.d.ts +1 -0
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +12 -0
- package/dist/astryx.umd.js +32 -32
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/useInputContainer.d.ts.map +1 -1
- package/dist/hooks/useInputContainer.js +29 -1
- package/package.json +2 -2
- package/src/CheckboxInput/CheckboxInput.test.tsx +33 -0
- package/src/Field/FieldLabel.test.tsx +78 -0
- package/src/Field/FieldLabel.tsx +49 -2
- package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
- package/src/SelectableCard/SelectableCard.test.tsx +55 -0
- package/src/SelectableCard/SelectableCard.tsx +16 -0
- package/src/Switch/Switch.test.tsx +34 -0
- package/src/hooks/useInputContainer.test.tsx +180 -0
- package/src/hooks/useInputContainer.ts +36 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - /packages/cli/assets/templates/blocks/components/Field/ (showcase blocks)
|
|
11
11
|
* - /packages/core/locales/en.json (@astryx.field.required / @astryx.field.optional)
|
|
12
12
|
*/
|
|
13
|
-
import type
|
|
13
|
+
import { type ReactNode } from 'react';
|
|
14
14
|
import type { BaseProps } from '../BaseProps';
|
|
15
15
|
import { type IconType } from '../Icon';
|
|
16
16
|
export interface FieldLabelProps extends BaseProps<HTMLLabelElement> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldLabel.d.ts","sourceRoot":"","sources":["../../src/Field/FieldLabel.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"FieldLabel.d.ts","sourceRoot":"","sources":["../../src/Field/FieldLabel.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAkB,KAAK,SAAS,EAAiB,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAU5C,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAyD5D,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,gBAAgB,CAAC;IAClE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACjC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,OAAO,EACP,OAAO,EACP,YAAoB,EACpB,aAAqB,EACrB,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,aAAa,EACb,SAAS,EACT,KAAK,EACL,MAAM,EACN,GAAG,EACH,GAAG,IAAI,EACR,EAAE,eAAe,+BAwGjB;yBA1He,UAAU"}
|
package/dist/Field/FieldLabel.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* - /packages/cli/assets/templates/blocks/components/Field/ (showcase blocks)
|
|
15
15
|
* - /packages/core/locales/en.json (@astryx.field.required / @astryx.field.optional)
|
|
16
16
|
*/
|
|
17
|
+
import { useMemo, useRef } from 'react';
|
|
17
18
|
import * as stylex from '@stylexjs/stylex';
|
|
18
19
|
import { mergeProps } from "../utils/index.js";
|
|
19
20
|
import "../theme/tokens.stylex.js";
|
|
@@ -22,6 +23,7 @@ import { Icon, renderIconSlot } from "../Icon/index.js";
|
|
|
22
23
|
import { Tooltip } from "../Tooltip/index.js";
|
|
23
24
|
import { useTranslator } from "../i18n/index.js";
|
|
24
25
|
import { themeProps } from "../utils/themeProps.js";
|
|
26
|
+
import { useInputContainer } from "../hooks/index.js";
|
|
25
27
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
26
28
|
const styles = {
|
|
27
29
|
label: {
|
|
@@ -98,6 +100,35 @@ export function FieldLabel({
|
|
|
98
100
|
// associated with a group. Render it as a `<span>` instead, keeping all the
|
|
99
101
|
// label styling and slots. The group references it via `aria-labelledby`.
|
|
100
102
|
const LabelElement = isGroupLabel ? 'span' : 'label';
|
|
103
|
+
|
|
104
|
+
// Clicking the description forwards to the associated control, so the whole
|
|
105
|
+
// label area (label text + description) is one hit target — mirroring native
|
|
106
|
+
// `<label>` click behavior, which the description can't get from `htmlFor`
|
|
107
|
+
// because it stays a sibling `<span>` (nesting it in the `<label>` would fold
|
|
108
|
+
// it into the control's accessible name and double-announce it alongside
|
|
109
|
+
// `aria-describedby`). A group label names a group, not one control, so it
|
|
110
|
+
// has nothing to forward to.
|
|
111
|
+
const forwardsDescriptionClick = !isGroupLabel && inputID != null;
|
|
112
|
+
|
|
113
|
+
// Reuse `useInputContainer` — the same hook input wrappers use to forward
|
|
114
|
+
// clicks on non-interactive chrome to their control. It skips nested
|
|
115
|
+
// interactive content (a link/button inside a ReactNode description) and
|
|
116
|
+
// guards against forwarding during text selection, so the description needs
|
|
117
|
+
// no bespoke click logic. The "input" is resolved from `inputID` lazily via
|
|
118
|
+
// a ref-shaped object, since FieldLabel points at the control by id rather
|
|
119
|
+
// than holding a ref to it.
|
|
120
|
+
const descriptionRef = useRef(null);
|
|
121
|
+
const controlRef = useMemo(() => ({
|
|
122
|
+
get current() {
|
|
123
|
+
return inputID == null ? null : descriptionRef.current?.ownerDocument.getElementById(inputID) ?? null;
|
|
124
|
+
},
|
|
125
|
+
set current(_value) {}
|
|
126
|
+
}), [inputID]);
|
|
127
|
+
const descriptionClickProps = useInputContainer({
|
|
128
|
+
containerRef: descriptionRef,
|
|
129
|
+
inputRef: controlRef,
|
|
130
|
+
disabled: !forwardsDescriptionClick
|
|
131
|
+
});
|
|
101
132
|
const labelContent = /*#__PURE__*/_jsxs(_Fragment, {
|
|
102
133
|
children: [labelIcon && renderIconSlot(labelIcon, {
|
|
103
134
|
size: 'sm',
|
|
@@ -132,15 +163,23 @@ export function FieldLabel({
|
|
|
132
163
|
...mergeProps(themeProps('field-label'), stylex.props(styles.label, isDisabled && styles.labelDisabled, isLabelHidden && styles.srOnly, xstyle), className, style),
|
|
133
164
|
children: labelContent
|
|
134
165
|
}), description && /*#__PURE__*/_jsx("span", {
|
|
166
|
+
ref: forwardsDescriptionClick ? descriptionRef : undefined,
|
|
135
167
|
id: descriptionID,
|
|
168
|
+
...(forwardsDescriptionClick ? descriptionClickProps : undefined),
|
|
136
169
|
...{
|
|
137
170
|
0: {
|
|
138
171
|
className: "x9ynric x141an7d x1ltkj2j x1sodnla xv1l7n4"
|
|
139
172
|
},
|
|
173
|
+
2: {
|
|
174
|
+
className: "x9ynric x141an7d x1ltkj2j x1sodnla xv1l7n4 x1ypdohk"
|
|
175
|
+
},
|
|
140
176
|
1: {
|
|
141
177
|
className: "x9ynric x141an7d x1ltkj2j x1sodnla xv1l7n4 xng3xce xzpqnlu xjm9jq1 x1o0tod xkdpibf xb3r6kr x1717udv x47corl x10l6tqk x13vifvy x87ps6o xuxw1ft x1i1rx1s"
|
|
178
|
+
},
|
|
179
|
+
3: {
|
|
180
|
+
className: "x9ynric x141an7d x1ltkj2j x1sodnla xv1l7n4 x1ypdohk xng3xce xzpqnlu xjm9jq1 x1o0tod xkdpibf xb3r6kr x1717udv x47corl x10l6tqk x13vifvy x87ps6o xuxw1ft x1i1rx1s"
|
|
142
181
|
}
|
|
143
|
-
}[!!isLabelHidden << 0],
|
|
182
|
+
}[!!forwardsDescriptionClick << 1 | !!isLabelHidden << 0],
|
|
144
183
|
children: description
|
|
145
184
|
})]
|
|
146
185
|
});
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*
|
|
19
19
|
* A hidden <input type="checkbox"> inside the card provides the accessible
|
|
20
20
|
* role, label, and checked state — the card surface itself has no role/tabIndex.
|
|
21
|
+
* Space toggles it natively; Enter is wired up as an additional toggle key.
|
|
21
22
|
*
|
|
22
23
|
* For static display, use Card.
|
|
23
24
|
* For navigation or action cards, use ClickableCard.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectableCard.d.ts","sourceRoot":"","sources":["../../src/SelectableCard/SelectableCard.tsx"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"SelectableCard.d.ts","sourceRoot":"","sources":["../../src/SelectableCard/SelectableCard.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EACL,KAAK,SAAS,EAKd,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAGtE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAkJ5C,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IACtE,yCAAyC;IACzC,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAE1B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,UAAU,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,QAAQ,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;IAExC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,yBAAyB;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,UAAU,EACV,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,UAAkB,EAClB,QAAQ,EACR,OAAO,EACP,OAAmB,EACnB,SAAkB,EAClB,KAAK,EACL,MAAM,EACN,QAAQ,EACR,GAAG,EACH,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,aAAa,EACxB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,mBAAmB,+BA0FrB;yBA7Ge,cAAc"}
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
*
|
|
23
23
|
* A hidden <input type="checkbox"> inside the card provides the accessible
|
|
24
24
|
* role, label, and checked state — the card surface itself has no role/tabIndex.
|
|
25
|
+
* Space toggles it natively; Enter is wired up as an additional toggle key.
|
|
25
26
|
*
|
|
26
27
|
* For static display, use Card.
|
|
27
28
|
* For navigation or action cards, use ClickableCard.
|
|
@@ -222,6 +223,16 @@ export function SelectableCard({
|
|
|
222
223
|
onChange(!isSelected);
|
|
223
224
|
}
|
|
224
225
|
}, [isDisabled, isSelected, onChange]);
|
|
226
|
+
|
|
227
|
+
// The focusable control is a native checkbox, which toggles on Space but
|
|
228
|
+
// ignores Enter. Add Enter as an extra toggle key; Space keeps its native
|
|
229
|
+
// handling, so we deliberately do not toggle on Space here (would double).
|
|
230
|
+
const handleKeyDown = useCallback(event => {
|
|
231
|
+
if (!isDisabled && event.key === 'Enter') {
|
|
232
|
+
event.preventDefault();
|
|
233
|
+
onChange(!isSelected);
|
|
234
|
+
}
|
|
235
|
+
}, [isDisabled, isSelected, onChange]);
|
|
225
236
|
const {
|
|
226
237
|
onClick,
|
|
227
238
|
onMouseUp
|
|
@@ -265,6 +276,7 @@ export function SelectableCard({
|
|
|
265
276
|
"aria-label": label,
|
|
266
277
|
disabled: isDisabled,
|
|
267
278
|
onChange: () => onChange(!isSelected),
|
|
279
|
+
onKeyDown: handleKeyDown,
|
|
268
280
|
...{
|
|
269
281
|
className: "x10l6tqk x1i1rx1s xjm9jq1 x1717udv xkdpibf xb3r6kr xzpqnlu xuxw1ft xc342km"
|
|
270
282
|
}
|