@dloizides/ui-forms 1.15.0 → 1.16.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/dist/index.d.mts +57 -1
- package/dist/index.d.ts +57 -1
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +25 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -970,4 +970,60 @@ declare function suggestOptions(options: readonly ControlOption[], query: string
|
|
|
970
970
|
/** True when `text` is non-empty yet matches no option's value or label exactly (case-insensitive). */
|
|
971
971
|
declare function isUnmatched(options: readonly ControlOption[], text: string): boolean;
|
|
972
972
|
|
|
973
|
-
|
|
973
|
+
/**
|
|
974
|
+
* Group selection — the pure tri-state logic behind a "select all" / "select this category"
|
|
975
|
+
* control, kept out of any component so it is testable as LOGIC rather than through the DOM.
|
|
976
|
+
*
|
|
977
|
+
* ## Why it lives here and not in @dloizides/ui-tables
|
|
978
|
+
*
|
|
979
|
+
* `ui-tables` already had this arithmetic inside `DataTable/selection.ts`, but deliberately
|
|
980
|
+
* unexported: its tri-state is a `const enum`, which in a published `.d.ts` is an ambient const
|
|
981
|
+
* enum that every `isolatedModules` consumer rejects. It is also page-scoped and wired to the
|
|
982
|
+
* table's select-all banner. So the second consumer (a 12-tile console picker with no table in
|
|
983
|
+
* sight, and no reason to pull a table package into its bundle budget) could not reach it.
|
|
984
|
+
*
|
|
985
|
+
* This module is the extraction: domain-neutral (keys in, keys out — nothing here knows what a
|
|
986
|
+
* key *is*), component-free, and crossing the package boundary as a plain interface rather than
|
|
987
|
+
* an enum. `ui-tables` can adopt it and delete its private copy.
|
|
988
|
+
*/
|
|
989
|
+
/**
|
|
990
|
+
* A group's tri-state, as two booleans rather than an enum.
|
|
991
|
+
*
|
|
992
|
+
* `all` and `some` are mutually exclusive: a fully selected group is `{ all: true, some: false }`,
|
|
993
|
+
* so a caller can branch on `all` then `some` without re-deriving "partial" itself. Both false
|
|
994
|
+
* means nothing in the group is selected — which is also what an EMPTY group reports, because an
|
|
995
|
+
* empty group is neither fully nor partially selected.
|
|
996
|
+
*/
|
|
997
|
+
interface GroupSelection {
|
|
998
|
+
/** Every key in the group is selected (never true for an empty group). */
|
|
999
|
+
readonly all: boolean;
|
|
1000
|
+
/** At least one, but not every, key in the group is selected — the mixed/indeterminate state. */
|
|
1001
|
+
readonly some: boolean;
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Resolve a group's tri-state from the selection ∩ the group.
|
|
1005
|
+
*
|
|
1006
|
+
* Scoped to the GROUP, not to the whole selection: selected keys OUTSIDE the group must never
|
|
1007
|
+
* make this group look partially selected.
|
|
1008
|
+
*/
|
|
1009
|
+
declare function resolveGroupSelection<T>(selected: readonly T[], groupKeys: readonly T[]): GroupSelection;
|
|
1010
|
+
/**
|
|
1011
|
+
* The value an `aria-checked` / `accessibilityState` consumer needs for a tri-state control.
|
|
1012
|
+
*
|
|
1013
|
+
* A partially selected group is `'mixed'`, which is what makes a screen reader announce the
|
|
1014
|
+
* control honestly instead of claiming the whole category is on.
|
|
1015
|
+
*/
|
|
1016
|
+
declare function groupAriaChecked(state: GroupSelection): boolean | 'mixed';
|
|
1017
|
+
/**
|
|
1018
|
+
* Toggle a whole group, returning the NEXT selection array. Pure — never mutates the input.
|
|
1019
|
+
*
|
|
1020
|
+
* All-on → off. Partial or off → on: the conventional behaviour, and the one a mixed checkbox
|
|
1021
|
+
* looks like it will do. Keys OUTSIDE the group always survive untouched, so a category control
|
|
1022
|
+
* can never silently clear a selection it does not own.
|
|
1023
|
+
*
|
|
1024
|
+
* `order`, when given, is the canonical key order the result is sorted into (catalogue order, say)
|
|
1025
|
+
* so the selection does not carry click order around. Without it, newly added keys are appended.
|
|
1026
|
+
*/
|
|
1027
|
+
declare function toggleGroupSelection<T>(selected: readonly T[], groupKeys: readonly T[], order?: readonly T[]): T[];
|
|
1028
|
+
|
|
1029
|
+
export { AnchoredMenu, type AnchoredMenuColors, type AnchoredMenuProps, type ChipOption, ChipSelector, type ChipSelectorProps, type ChipSingleSelectRole, type ChipVariant, type ControlOption, DEFAULT_MAX_RECENTS, DEFAULT_OPTIONAL_LABEL, DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS, DEFAULT_TYPEAHEAD_MIN_CHARS, DateRangeControl, type DateRangeControlProps, type DateRangeValue, Field, type FieldChildContext, type FieldChildren, type FieldLabelVariant, type FieldMarker, type FieldProps, type FieldSpacing, FormActions, type FormActionsProps, FormCell, type FormCellProps, FormCheckbox, type FormCheckboxProps, FormField, type FormFieldProps, FormGrid, type FormGridProps, FormSection, type FormSectionProps, FormSwitch, type FormSwitchProps, type GroupSelection, type RecentValues, SelectControl, type SelectControlProps, type ThemedInput, ThemedTextInput, type ThemedTextInputProps, TypeaheadControl, type TypeaheadControlProps, type UseThemedInputOptions, controlStyles, groupAriaChecked, isUnmatched, resolveGroupSelection, suggestOptions, toggleGroupSelection, useRecentValues, useThemedInput };
|
package/dist/index.d.ts
CHANGED
|
@@ -970,4 +970,60 @@ declare function suggestOptions(options: readonly ControlOption[], query: string
|
|
|
970
970
|
/** True when `text` is non-empty yet matches no option's value or label exactly (case-insensitive). */
|
|
971
971
|
declare function isUnmatched(options: readonly ControlOption[], text: string): boolean;
|
|
972
972
|
|
|
973
|
-
|
|
973
|
+
/**
|
|
974
|
+
* Group selection — the pure tri-state logic behind a "select all" / "select this category"
|
|
975
|
+
* control, kept out of any component so it is testable as LOGIC rather than through the DOM.
|
|
976
|
+
*
|
|
977
|
+
* ## Why it lives here and not in @dloizides/ui-tables
|
|
978
|
+
*
|
|
979
|
+
* `ui-tables` already had this arithmetic inside `DataTable/selection.ts`, but deliberately
|
|
980
|
+
* unexported: its tri-state is a `const enum`, which in a published `.d.ts` is an ambient const
|
|
981
|
+
* enum that every `isolatedModules` consumer rejects. It is also page-scoped and wired to the
|
|
982
|
+
* table's select-all banner. So the second consumer (a 12-tile console picker with no table in
|
|
983
|
+
* sight, and no reason to pull a table package into its bundle budget) could not reach it.
|
|
984
|
+
*
|
|
985
|
+
* This module is the extraction: domain-neutral (keys in, keys out — nothing here knows what a
|
|
986
|
+
* key *is*), component-free, and crossing the package boundary as a plain interface rather than
|
|
987
|
+
* an enum. `ui-tables` can adopt it and delete its private copy.
|
|
988
|
+
*/
|
|
989
|
+
/**
|
|
990
|
+
* A group's tri-state, as two booleans rather than an enum.
|
|
991
|
+
*
|
|
992
|
+
* `all` and `some` are mutually exclusive: a fully selected group is `{ all: true, some: false }`,
|
|
993
|
+
* so a caller can branch on `all` then `some` without re-deriving "partial" itself. Both false
|
|
994
|
+
* means nothing in the group is selected — which is also what an EMPTY group reports, because an
|
|
995
|
+
* empty group is neither fully nor partially selected.
|
|
996
|
+
*/
|
|
997
|
+
interface GroupSelection {
|
|
998
|
+
/** Every key in the group is selected (never true for an empty group). */
|
|
999
|
+
readonly all: boolean;
|
|
1000
|
+
/** At least one, but not every, key in the group is selected — the mixed/indeterminate state. */
|
|
1001
|
+
readonly some: boolean;
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Resolve a group's tri-state from the selection ∩ the group.
|
|
1005
|
+
*
|
|
1006
|
+
* Scoped to the GROUP, not to the whole selection: selected keys OUTSIDE the group must never
|
|
1007
|
+
* make this group look partially selected.
|
|
1008
|
+
*/
|
|
1009
|
+
declare function resolveGroupSelection<T>(selected: readonly T[], groupKeys: readonly T[]): GroupSelection;
|
|
1010
|
+
/**
|
|
1011
|
+
* The value an `aria-checked` / `accessibilityState` consumer needs for a tri-state control.
|
|
1012
|
+
*
|
|
1013
|
+
* A partially selected group is `'mixed'`, which is what makes a screen reader announce the
|
|
1014
|
+
* control honestly instead of claiming the whole category is on.
|
|
1015
|
+
*/
|
|
1016
|
+
declare function groupAriaChecked(state: GroupSelection): boolean | 'mixed';
|
|
1017
|
+
/**
|
|
1018
|
+
* Toggle a whole group, returning the NEXT selection array. Pure — never mutates the input.
|
|
1019
|
+
*
|
|
1020
|
+
* All-on → off. Partial or off → on: the conventional behaviour, and the one a mixed checkbox
|
|
1021
|
+
* looks like it will do. Keys OUTSIDE the group always survive untouched, so a category control
|
|
1022
|
+
* can never silently clear a selection it does not own.
|
|
1023
|
+
*
|
|
1024
|
+
* `order`, when given, is the canonical key order the result is sorted into (catalogue order, say)
|
|
1025
|
+
* so the selection does not carry click order around. Without it, newly added keys are appended.
|
|
1026
|
+
*/
|
|
1027
|
+
declare function toggleGroupSelection<T>(selected: readonly T[], groupKeys: readonly T[], order?: readonly T[]): T[];
|
|
1028
|
+
|
|
1029
|
+
export { AnchoredMenu, type AnchoredMenuColors, type AnchoredMenuProps, type ChipOption, ChipSelector, type ChipSelectorProps, type ChipSingleSelectRole, type ChipVariant, type ControlOption, DEFAULT_MAX_RECENTS, DEFAULT_OPTIONAL_LABEL, DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS, DEFAULT_TYPEAHEAD_MIN_CHARS, DateRangeControl, type DateRangeControlProps, type DateRangeValue, Field, type FieldChildContext, type FieldChildren, type FieldLabelVariant, type FieldMarker, type FieldProps, type FieldSpacing, FormActions, type FormActionsProps, FormCell, type FormCellProps, FormCheckbox, type FormCheckboxProps, FormField, type FormFieldProps, FormGrid, type FormGridProps, FormSection, type FormSectionProps, FormSwitch, type FormSwitchProps, type GroupSelection, type RecentValues, SelectControl, type SelectControlProps, type ThemedInput, ThemedTextInput, type ThemedTextInputProps, TypeaheadControl, type TypeaheadControlProps, type UseThemedInputOptions, controlStyles, groupAriaChecked, isUnmatched, resolveGroupSelection, suggestOptions, toggleGroupSelection, useRecentValues, useThemedInput };
|
package/dist/index.js
CHANGED
|
@@ -1679,6 +1679,30 @@ function DateRangeControl({
|
|
|
1679
1679
|
] });
|
|
1680
1680
|
}
|
|
1681
1681
|
|
|
1682
|
+
// src/groupSelection/groupSelection.ts
|
|
1683
|
+
var NONE = 0;
|
|
1684
|
+
function countSelected(selected, groupKeys) {
|
|
1685
|
+
return groupKeys.filter((key) => selected.includes(key)).length;
|
|
1686
|
+
}
|
|
1687
|
+
function resolveGroupSelection(selected, groupKeys) {
|
|
1688
|
+
const count = countSelected(selected, groupKeys);
|
|
1689
|
+
if (count === NONE) return { all: false, some: false };
|
|
1690
|
+
return count === groupKeys.length ? { all: true, some: false } : { all: false, some: true };
|
|
1691
|
+
}
|
|
1692
|
+
function groupAriaChecked(state) {
|
|
1693
|
+
if (state.all) return true;
|
|
1694
|
+
return state.some ? "mixed" : false;
|
|
1695
|
+
}
|
|
1696
|
+
function toggleGroupSelection(selected, groupKeys, order) {
|
|
1697
|
+
const { all } = resolveGroupSelection(selected, groupKeys);
|
|
1698
|
+
if (all) return selected.filter((key) => !groupKeys.includes(key));
|
|
1699
|
+
const merged = [...selected];
|
|
1700
|
+
groupKeys.forEach((key) => {
|
|
1701
|
+
if (!merged.includes(key)) merged.push(key);
|
|
1702
|
+
});
|
|
1703
|
+
return order === void 0 ? merged : order.filter((key) => merged.includes(key));
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1682
1706
|
exports.AnchoredMenu = AnchoredMenu;
|
|
1683
1707
|
exports.ChipSelector = ChipSelector;
|
|
1684
1708
|
exports.DEFAULT_MAX_RECENTS = DEFAULT_MAX_RECENTS;
|
|
@@ -1698,8 +1722,11 @@ exports.SelectControl = SelectControl;
|
|
|
1698
1722
|
exports.ThemedTextInput = ThemedTextInput;
|
|
1699
1723
|
exports.TypeaheadControl = TypeaheadControl;
|
|
1700
1724
|
exports.controlStyles = controlStyles;
|
|
1725
|
+
exports.groupAriaChecked = groupAriaChecked;
|
|
1701
1726
|
exports.isUnmatched = isUnmatched;
|
|
1727
|
+
exports.resolveGroupSelection = resolveGroupSelection;
|
|
1702
1728
|
exports.suggestOptions = suggestOptions;
|
|
1729
|
+
exports.toggleGroupSelection = toggleGroupSelection;
|
|
1703
1730
|
exports.useRecentValues = useRecentValues;
|
|
1704
1731
|
exports.useThemedInput = useThemedInput;
|
|
1705
1732
|
//# sourceMappingURL=index.js.map
|