@octaviaflow/core 3.0.5 → 3.0.7
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/components/Button/Button.d.ts.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.d.ts +9 -1
- package/dist/components/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/components/Radio/Radio.d.ts.map +1 -1
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Switch/Switch.d.ts.map +1 -1
- package/dist/components/Textarea/Textarea.d.ts.map +1 -1
- package/dist/index.cjs +124 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +124 -29
- package/dist/index.js.map +1 -1
- package/dist/stories/state-matrix.d.ts +74 -0
- package/dist/stories/state-matrix.d.ts.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/utils/a11y.d.ts +70 -0
- package/dist/utils/a11y.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -607,6 +607,32 @@ function Breadcrumb({
|
|
|
607
607
|
import { motion as motion2 } from "framer-motion";
|
|
608
608
|
import { useRef as useRef3 } from "react";
|
|
609
609
|
import { useButton } from "react-aria";
|
|
610
|
+
|
|
611
|
+
// src/utils/a11y.ts
|
|
612
|
+
function resolveAccessibleName(input) {
|
|
613
|
+
if (input.ariaLabelledby) {
|
|
614
|
+
return { "aria-labelledby": input.ariaLabelledby };
|
|
615
|
+
}
|
|
616
|
+
if (input.ariaLabel) {
|
|
617
|
+
return { "aria-label": input.ariaLabel };
|
|
618
|
+
}
|
|
619
|
+
if (typeof input.label === "string" && input.label.trim().length > 0) {
|
|
620
|
+
return { "aria-label": input.label };
|
|
621
|
+
}
|
|
622
|
+
for (const candidate of input.fallbacks ?? []) {
|
|
623
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
624
|
+
return { "aria-label": candidate };
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (process.env.NODE_ENV !== "production") {
|
|
628
|
+
console.error(
|
|
629
|
+
`[@octaviaflow/core ${input.componentName}] No accessible name. Pass a string \`label\`, or \`aria-label\`, or \`aria-labelledby\` so screen readers can announce this control.`
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
return { "aria-label": `Unlabeled ${input.componentName}` };
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// src/components/Button/Button.tsx
|
|
610
636
|
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
611
637
|
function Button({
|
|
612
638
|
variant = "primary",
|
|
@@ -624,11 +650,19 @@ function Button({
|
|
|
624
650
|
const ref = useRef3(null);
|
|
625
651
|
const isDisabled = disabled || loading;
|
|
626
652
|
const resolvedType = type ?? "button";
|
|
653
|
+
const hasVisibleText = typeof children === "string" ? children.trim().length > 0 : Boolean(children);
|
|
654
|
+
const needsAriaName = !hasVisibleText;
|
|
655
|
+
const ariaNameProps = needsAriaName ? resolveAccessibleName({
|
|
656
|
+
ariaLabel: props["aria-label"],
|
|
657
|
+
ariaLabelledby: props["aria-labelledby"],
|
|
658
|
+
componentName: "Button"
|
|
659
|
+
}) : void 0;
|
|
627
660
|
const { buttonProps } = useButton(
|
|
628
661
|
{
|
|
629
662
|
isDisabled,
|
|
630
663
|
onPress: props.onClick,
|
|
631
|
-
type: resolvedType
|
|
664
|
+
type: resolvedType,
|
|
665
|
+
...ariaNameProps ?? {}
|
|
632
666
|
},
|
|
633
667
|
ref
|
|
634
668
|
);
|
|
@@ -644,7 +678,7 @@ function Button({
|
|
|
644
678
|
onBlur: _onBlur,
|
|
645
679
|
...passthroughProps
|
|
646
680
|
} = props;
|
|
647
|
-
return /* @__PURE__ */
|
|
681
|
+
return /* @__PURE__ */ jsx10(
|
|
648
682
|
motion2.button,
|
|
649
683
|
{
|
|
650
684
|
...passthroughProps,
|
|
@@ -662,27 +696,32 @@ function Button({
|
|
|
662
696
|
"data-loading": loading || void 0,
|
|
663
697
|
whileTap: isDisabled ? void 0 : { scale: 0.97 },
|
|
664
698
|
transition: { duration: 0.1 },
|
|
665
|
-
children: [
|
|
666
|
-
/* @__PURE__ */
|
|
667
|
-
|
|
668
|
-
children && /* @__PURE__ */ jsx10("span", { className: "ods-btn__label", children }),
|
|
669
|
-
rightIcon && /* @__PURE__ */ jsx10("span", { className: "ods-btn__icon ods-btn__icon--right", children: rightIcon })
|
|
670
|
-
] }),
|
|
671
|
-
loading && /* @__PURE__ */ jsx10("span", { className: "ods-btn__spinner", role: "status", "aria-label": "Loading", children: /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 24 24", width: "16", height: "16", "aria-hidden": "true", children: /* @__PURE__ */ jsx10(
|
|
672
|
-
"circle",
|
|
699
|
+
children: /* @__PURE__ */ jsxs10("span", { className: "ods-btn__content", children: [
|
|
700
|
+
loading ? /* @__PURE__ */ jsx10(
|
|
701
|
+
"span",
|
|
673
702
|
{
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
703
|
+
className: "ods-btn__icon ods-btn__icon--left ods-btn__icon--spinner",
|
|
704
|
+
role: "status",
|
|
705
|
+
"aria-label": "Loading",
|
|
706
|
+
children: /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 24 24", width: "16", height: "16", "aria-hidden": "true", children: /* @__PURE__ */ jsx10(
|
|
707
|
+
"circle",
|
|
708
|
+
{
|
|
709
|
+
cx: "12",
|
|
710
|
+
cy: "12",
|
|
711
|
+
r: "10",
|
|
712
|
+
fill: "none",
|
|
713
|
+
stroke: "currentColor",
|
|
714
|
+
strokeWidth: "2.5",
|
|
715
|
+
strokeLinecap: "round",
|
|
716
|
+
strokeDasharray: "32",
|
|
717
|
+
strokeDashoffset: "12"
|
|
718
|
+
}
|
|
719
|
+
) })
|
|
683
720
|
}
|
|
684
|
-
)
|
|
685
|
-
|
|
721
|
+
) : leftIcon && /* @__PURE__ */ jsx10("span", { className: "ods-btn__icon ods-btn__icon--left", children: leftIcon }),
|
|
722
|
+
children && /* @__PURE__ */ jsx10("span", { className: "ods-btn__label", children }),
|
|
723
|
+
rightIcon && !loading && /* @__PURE__ */ jsx10("span", { className: "ods-btn__icon ods-btn__icon--right", children: rightIcon })
|
|
724
|
+
] })
|
|
686
725
|
}
|
|
687
726
|
);
|
|
688
727
|
}
|
|
@@ -2454,13 +2493,19 @@ function Checkbox({
|
|
|
2454
2493
|
defaultSelected: defaultChecked,
|
|
2455
2494
|
onChange
|
|
2456
2495
|
});
|
|
2496
|
+
const ariaNameProps = resolveAccessibleName({
|
|
2497
|
+
label,
|
|
2498
|
+
ariaLabel: props["aria-label"],
|
|
2499
|
+
ariaLabelledby: props["aria-labelledby"],
|
|
2500
|
+
componentName: "Checkbox"
|
|
2501
|
+
});
|
|
2457
2502
|
const { inputProps } = useCheckbox(
|
|
2458
2503
|
{
|
|
2459
2504
|
isSelected: state.isSelected,
|
|
2460
2505
|
isIndeterminate: indeterminate,
|
|
2461
2506
|
isDisabled: disabled,
|
|
2462
2507
|
onChange,
|
|
2463
|
-
|
|
2508
|
+
...ariaNameProps
|
|
2464
2509
|
},
|
|
2465
2510
|
state,
|
|
2466
2511
|
ref
|
|
@@ -6363,11 +6408,27 @@ function MenuPopup({
|
|
|
6363
6408
|
}
|
|
6364
6409
|
return null;
|
|
6365
6410
|
}
|
|
6366
|
-
function DropdownMenu({
|
|
6411
|
+
function DropdownMenu({
|
|
6412
|
+
trigger,
|
|
6413
|
+
items,
|
|
6414
|
+
align = "start",
|
|
6415
|
+
className,
|
|
6416
|
+
"aria-label": ariaLabel,
|
|
6417
|
+
"aria-labelledby": ariaLabelledby
|
|
6418
|
+
}) {
|
|
6367
6419
|
const triggerRef = useRef12(null);
|
|
6368
6420
|
const state = $e3403870bfb691da$export$79fefeb1c2091ac3({});
|
|
6369
6421
|
const { menuTriggerProps } = useMenuTrigger({}, state, triggerRef);
|
|
6370
|
-
const
|
|
6422
|
+
const ariaNameProps = resolveAccessibleName({
|
|
6423
|
+
ariaLabel,
|
|
6424
|
+
ariaLabelledby,
|
|
6425
|
+
componentName: "DropdownMenu",
|
|
6426
|
+
fallbacks: [typeof trigger === "string" ? trigger : void 0]
|
|
6427
|
+
});
|
|
6428
|
+
const { buttonProps } = useButton3(
|
|
6429
|
+
{ ...menuTriggerProps, ...ariaNameProps },
|
|
6430
|
+
triggerRef
|
|
6431
|
+
);
|
|
6371
6432
|
const { onDrag, onDragStart, onDragEnd, onAnimationStart, ...safeTriggerProps } = buttonProps;
|
|
6372
6433
|
return /* @__PURE__ */ jsxs28(Fragment6, { children: [
|
|
6373
6434
|
/* @__PURE__ */ jsx29("button", { ...safeTriggerProps, ref: triggerRef, className: "ods-dropdown__trigger", children: trigger }),
|
|
@@ -10181,11 +10242,18 @@ function Radio({
|
|
|
10181
10242
|
}) {
|
|
10182
10243
|
const state = useRadioGroupContext();
|
|
10183
10244
|
const ref = useRef24(null);
|
|
10245
|
+
const ariaNameProps = resolveAccessibleName({
|
|
10246
|
+
label,
|
|
10247
|
+
ariaLabel: props["aria-label"],
|
|
10248
|
+
ariaLabelledby: props["aria-labelledby"],
|
|
10249
|
+
componentName: "Radio",
|
|
10250
|
+
fallbacks: [value]
|
|
10251
|
+
});
|
|
10184
10252
|
const { inputProps } = useRadio(
|
|
10185
10253
|
{
|
|
10186
10254
|
value,
|
|
10187
10255
|
isDisabled: disabled,
|
|
10188
|
-
|
|
10256
|
+
...ariaNameProps
|
|
10189
10257
|
},
|
|
10190
10258
|
state,
|
|
10191
10259
|
ref
|
|
@@ -10783,6 +10851,15 @@ function Select({
|
|
|
10783
10851
|
(o) => o.label.toLowerCase().includes(q) || o.description?.toLowerCase().includes(q)
|
|
10784
10852
|
);
|
|
10785
10853
|
}, [options, searchQuery, searchable]);
|
|
10854
|
+
const ariaNameProps = useMemo10(
|
|
10855
|
+
() => resolveAccessibleName({
|
|
10856
|
+
label,
|
|
10857
|
+
ariaLabel,
|
|
10858
|
+
ariaLabelledby: ariaLabelledBy,
|
|
10859
|
+
componentName: "Select"
|
|
10860
|
+
}),
|
|
10861
|
+
[label, ariaLabel, ariaLabelledBy]
|
|
10862
|
+
);
|
|
10786
10863
|
const ariaProps = useMemo10(() => {
|
|
10787
10864
|
const items = filteredOptions.map((o) => ({
|
|
10788
10865
|
key: o.value,
|
|
@@ -10791,7 +10868,10 @@ function Select({
|
|
|
10791
10868
|
isDisabled: o.disabled
|
|
10792
10869
|
}));
|
|
10793
10870
|
const props = {
|
|
10794
|
-
|
|
10871
|
+
// Visible string label when present; otherwise rely on the aria-*
|
|
10872
|
+
// props for screen-reader name.
|
|
10873
|
+
label: typeof label === "string" ? label : void 0,
|
|
10874
|
+
...ariaNameProps,
|
|
10795
10875
|
items,
|
|
10796
10876
|
children: (item) => /* @__PURE__ */ jsx66($05678f3aee5e7d1a$export$6d08773d2e66f8f2, { textValue: item.label, children: item.label }, item.key),
|
|
10797
10877
|
isDisabled: disabled,
|
|
@@ -10807,7 +10887,7 @@ function Select({
|
|
|
10807
10887
|
props.defaultSelectedKey = defaultValue;
|
|
10808
10888
|
}
|
|
10809
10889
|
return props;
|
|
10810
|
-
}, [filteredOptions, label, disabled, value, defaultValue, onChange]);
|
|
10890
|
+
}, [filteredOptions, label, disabled, value, defaultValue, onChange, ariaNameProps]);
|
|
10811
10891
|
const state = $29256f53a2edafe9$export$5159ec8b34d4ec12(ariaProps);
|
|
10812
10892
|
const { triggerProps, menuProps } = useSelect(ariaProps, state, triggerRef);
|
|
10813
10893
|
const { buttonProps } = useButton4(triggerProps, triggerRef);
|
|
@@ -12166,12 +12246,18 @@ function Switch({
|
|
|
12166
12246
|
defaultSelected: defaultChecked,
|
|
12167
12247
|
onChange
|
|
12168
12248
|
});
|
|
12249
|
+
const ariaNameProps = resolveAccessibleName({
|
|
12250
|
+
label,
|
|
12251
|
+
ariaLabel: props["aria-label"],
|
|
12252
|
+
ariaLabelledby: props["aria-labelledby"],
|
|
12253
|
+
componentName: "Switch"
|
|
12254
|
+
});
|
|
12169
12255
|
const { inputProps } = useSwitch(
|
|
12170
12256
|
{
|
|
12171
12257
|
isSelected: state.isSelected,
|
|
12172
12258
|
isDisabled: disabled,
|
|
12173
12259
|
onChange,
|
|
12174
|
-
|
|
12260
|
+
...ariaNameProps
|
|
12175
12261
|
},
|
|
12176
12262
|
state,
|
|
12177
12263
|
ref
|
|
@@ -12617,9 +12703,18 @@ function Textarea({
|
|
|
12617
12703
|
const ref = useRef32(null);
|
|
12618
12704
|
const errorId = useId4();
|
|
12619
12705
|
const [charCount, setCharCount] = useState26(() => String(value ?? defaultValue ?? "").length);
|
|
12706
|
+
const ariaNameProps = resolveAccessibleName({
|
|
12707
|
+
label,
|
|
12708
|
+
ariaLabel: props["aria-label"],
|
|
12709
|
+
ariaLabelledby: props["aria-labelledby"],
|
|
12710
|
+
componentName: "Textarea"
|
|
12711
|
+
});
|
|
12620
12712
|
const { labelProps, inputProps } = useTextField2(
|
|
12621
12713
|
{
|
|
12622
|
-
|
|
12714
|
+
// Pass a string `label` only when caller gave a string; otherwise rely
|
|
12715
|
+
// on the aria-* props from resolveAccessibleName.
|
|
12716
|
+
label: typeof label === "string" ? label : void 0,
|
|
12717
|
+
...ariaNameProps,
|
|
12623
12718
|
isDisabled: disabled,
|
|
12624
12719
|
errorMessage,
|
|
12625
12720
|
validationState: error ? "invalid" : void 0,
|