@lumx/core 4.11.0-next.5 → 4.11.0-next.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.
@@ -4988,21 +4988,10 @@ table {
4988
4988
  /* Selection Chip group
4989
4989
  ========================================================================== */
4990
4990
  .lumx-selection-chip-group {
4991
- max-width: 100%;
4992
- }
4993
- .lumx-selection-chip-group:empty {
4994
- display: none;
4995
- }
4996
- .lumx-selection-chip-group__item {
4997
- display: flex;
4998
- overflow: hidden;
4991
+ align-content: flex-start;
4999
4992
  }
5000
- .lumx-selection-chip-group__chip {
5001
- overflow: hidden;
5002
- }
5003
- .lumx-selection-chip-group__chip .lumx-chip__label {
5004
- overflow: hidden;
5005
- text-overflow: ellipsis;
4993
+ .lumx-selection-chip-group, .lumx-selection-chip-group .lumx-chip, .lumx-selection-chip-group .lumx-chip__label {
4994
+ min-width: 0;
5006
4995
  }
5007
4996
 
5008
4997
  /* ==========================================================================
@@ -5020,6 +5009,22 @@ table {
5020
5009
  }
5021
5010
  .lumx-combobox-popover__scroll {
5022
5011
  overflow-y: auto;
5012
+ scroll-snap-type: y proximity;
5013
+ }
5014
+ @media (prefers-reduced-motion: no-preference) {
5015
+ .lumx-combobox-popover__scroll {
5016
+ scroll-behavior: smooth;
5017
+ }
5018
+ }
5019
+ .lumx-combobox-popover__scroll::before {
5020
+ content: "";
5021
+ display: block;
5022
+ scroll-snap-align: start;
5023
+ }
5024
+ .lumx-combobox-popover__scroll::after {
5025
+ content: "";
5026
+ display: block;
5027
+ scroll-snap-align: end;
5023
5028
  }
5024
5029
 
5025
5030
  .lumx-combobox-popover:empty, .lumx-combobox-popover:not(:has(.lumx-combobox-option)):not(:has(.lumx-combobox-state)):not(:has(.lumx-combobox-option-skeleton)),
@@ -0,0 +1,56 @@
1
+ import type { LumxClassName, HasClassName, HasTheme } from '../../types';
2
+ import type { Selector } from '../../types/Selector';
3
+ import type { ChipProps } from '.';
4
+ /**
5
+ * Framework-specific components injected by React/Vue wrappers.
6
+ */
7
+ export interface SelectionChipGroupComponents {
8
+ Chip: any;
9
+ ChipGroup: any;
10
+ Icon: any;
11
+ Text: any;
12
+ Tooltip: any;
13
+ }
14
+ /**
15
+ * Props that consumers can override per chip via getChipProps.
16
+ * Excludes internal/framework props that the core always controls.
17
+ */
18
+ export type ChipOverrideProps = Pick<ChipProps, 'isDisabled' | 'color' | 'isHighlighted' | 'isSelected' | 'className' | 'before' | 'after'>;
19
+ /**
20
+ * Defines the props of the component.
21
+ */
22
+ export interface SelectionChipGroupProps<O> extends HasClassName, HasTheme {
23
+ /** Option object id selector (either a property name or a function to get the id) */
24
+ getOptionId: Selector<O>;
25
+ /** Option object name selector. Falls back to the id if not defined */
26
+ getOptionName?: Selector<O, string | undefined | null>;
27
+ /** Selected options array */
28
+ value?: O[];
29
+ /** Label for accessibility (aria-label on the listbox) */
30
+ label: string;
31
+ /** Label for the remove action (visually hidden text appended to each chip) */
32
+ chipRemoveLabel?: string;
33
+ /** Disabled state for all chips */
34
+ isDisabled?: boolean;
35
+ /** Customize chip props per option */
36
+ getChipProps?: (option: O) => Partial<ChipProps>;
37
+ /** Ref for the container element */
38
+ ref?: any;
39
+ }
40
+ /**
41
+ * Component display name.
42
+ */
43
+ export declare const COMPONENT_NAME = "SelectionChipGroup";
44
+ /**
45
+ * Component default class name and class prefix.
46
+ */
47
+ export declare const CLASSNAME: LumxClassName<typeof COMPONENT_NAME>;
48
+ /**
49
+ * SelectionChipGroup component.
50
+ * Renders a listbox of removable selection chips using component injection for framework-agnostic rendering.
51
+ *
52
+ * @param props Component props.
53
+ * @param components Framework-specific components injected by the wrapper (Chip, ChipGroup, Icon, Tooltip).
54
+ * @return JSX element, or null when value is empty.
55
+ */
56
+ export declare const SelectionChipGroup: <O>(props: SelectionChipGroupProps<O>, { Chip, ChipGroup, Icon, Text, Tooltip }: SelectionChipGroupComponents) => import("react").JSX.Element | null;
@@ -0,0 +1,18 @@
1
+ import { SetupOptions } from '../../../testing';
2
+ /**
3
+ * Mounts the component and returns common DOM elements / data needed in multiple tests further down.
4
+ */
5
+ export declare const setup: (propsOverride: any | undefined, { render, ...options }: SetupOptions<any>) => {
6
+ props: any;
7
+ selectionChipGroup: HTMLElement | null;
8
+ wrapper: Partial<import("../../../testing").SetupResult>;
9
+ };
10
+ interface CoreTestOptions extends SetupOptions<any> {
11
+ /**
12
+ * Render a stateful SelectionChipGroup that updates its own value on change.
13
+ * When provided, enables roving tabindex recovery tests.
14
+ */
15
+ renderStateful?: () => void;
16
+ }
17
+ declare const _default: (renderOptions: CoreTestOptions) => void;
18
+ export default _default;
@@ -0,0 +1,81 @@
1
+ import { ColorPalette, Size } from '../../constants';
2
+ import { HasTheme, HasAriaDisabled, JSXElement, LumxClassName, HasClassName, HasDisabled, CommonRef, GenericProps } from '../../types';
3
+ /**
4
+ * Chip sizes.
5
+ */
6
+ export type ChipSize = Extract<Size, 's' | 'm'>;
7
+ /**
8
+ * Defines the props of the component.
9
+ */
10
+ export interface ChipProps extends HasClassName, HasDisabled, HasTheme, HasAriaDisabled {
11
+ /** A component to be rendered after the content. */
12
+ after?: JSXElement;
13
+ /** A component to be rendered before the content. */
14
+ before?: JSXElement;
15
+ /** Color variant. */
16
+ color?: ColorPalette;
17
+ /** Whether the component is clickable or not. */
18
+ isClickable?: boolean;
19
+ /** Whether the chip is currently in a highlighted state or not. */
20
+ isHighlighted?: boolean;
21
+ /** Whether the component is selected or not. */
22
+ isSelected?: boolean;
23
+ /** Size variant. */
24
+ size?: ChipSize;
25
+ /** href for the chip if it is a link */
26
+ href?: string;
27
+ /** reference to the root element */
28
+ ref?: CommonRef;
29
+ /** On "after" element clicked callback. */
30
+ handleAfterClick?: (event: any) => void;
31
+ /** On element key down callback. */
32
+ handleKeyDown?: (event: any) => void;
33
+ /** On "before" element clicked callback. */
34
+ handleBeforeClick?: (event: any) => void;
35
+ /** On element clicked callback. */
36
+ handleClick?: (event: any) => void;
37
+ /** name of the prop for handling key down events */
38
+ keyDownProp?: string;
39
+ /** name of the prop for tab index */
40
+ tabIndexProp?: string;
41
+ /** Children */
42
+ children?: JSXElement;
43
+ /** Props to apply when the component is in a disabled state. */
44
+ disabledStateProps: GenericProps;
45
+ /** Whether the "after" element has a click handler. */
46
+ hasAfterClick?: boolean;
47
+ /** Whether the "before" element has a click handler. */
48
+ hasBeforeClick?: boolean;
49
+ /** Whether the component has a main click handler. */
50
+ hasOnClick?: boolean;
51
+ /** Whether any part of the component is disabled. */
52
+ isAnyDisabled?: boolean;
53
+ }
54
+ export type ChipPropsToOverride = 'disabledStateProps' | 'hasOnClick' | 'hasBeforeClick' | 'hasAfterClick' | 'before' | 'after' | 'keyDownProp' | 'tabIndexProp' | 'isAnyDisabled';
55
+ /**
56
+ * Component display name.
57
+ */
58
+ export declare const COMPONENT_NAME = "Chip";
59
+ /**
60
+ * Component default class name and class prefix.
61
+ */
62
+ export declare const CLASSNAME: LumxClassName<typeof COMPONENT_NAME>;
63
+ export declare const block: {
64
+ (additionalClasses: import("classnames/types").ClassValue[]): string;
65
+ (modifiers?: import("../../utils/classNames/bem/modifier").Modifier, additionalClasses?: import("classnames/types").ClassValue[]): string;
66
+ }, element: {
67
+ (elem: string, additionalClasses: import("classnames/types").ClassValue[]): string;
68
+ (elem: string, modifiers?: import("../../utils/classNames/bem/modifier").Modifier, additionalClasses?: import("classnames/types").ClassValue[]): string;
69
+ };
70
+ /**
71
+ * Component default props.
72
+ */
73
+ export declare const DEFAULT_PROPS: Partial<ChipProps>;
74
+ /**
75
+ * Chip component.
76
+ *
77
+ * @param props Component props.
78
+ * @param ref Component ref.
79
+ * @return React element.
80
+ */
81
+ export declare const Chip: (props: ChipProps) => import("react").JSX.Element;
@@ -0,0 +1,28 @@
1
+ import type { Selector } from '../../types/Selector';
2
+ /**
3
+ * Options for setting up selection chip group event handlers.
4
+ * All option accessors are wrapped in getters so that React/Vue can provide
5
+ * reactive values without the core needing to know about reactivity systems.
6
+ */
7
+ export interface SetupSelectionChipGroupEventsOptions<O> {
8
+ /** Getter for the current selected options array. */
9
+ getValue: () => O[] | undefined;
10
+ /** Getter for the option id selector. */
11
+ getOptionId: Selector<O>;
12
+ /** Callback when the option array changes. */
13
+ onChange: (newValue?: O[]) => void;
14
+ /** Getter for the chip group container element. */
15
+ getContainer: () => HTMLElement | null | undefined;
16
+ /** Getter for the associated input element (optional). */
17
+ getInput?: () => HTMLInputElement | null | undefined;
18
+ }
19
+ /**
20
+ * Attach delegated click and keydown event listeners on the chip group container,
21
+ * and optionally an input backspace handler.
22
+ *
23
+ * Uses addEventListener on the container element. Events bubble up from individual
24
+ * chips, so there is no need to re-attach listeners when chips change.
25
+ *
26
+ * @returns A cleanup function that removes all attached event listeners.
27
+ */
28
+ export declare function setupSelectionChipGroupEvents<O>(options: SetupSelectionChipGroupEventsOptions<O>): () => void;
@@ -17,6 +17,11 @@ export interface ComboboxInputProps extends HasClassName, HasTheme {
17
17
  toggleButtonProps?: Record<string, any>;
18
18
  /** Toggle callback for the chevron button. */
19
19
  handleToggle?(): void;
20
+ /**
21
+ * Controls how the combobox filters options as the user types.
22
+ * When `'off'`, the input is rendered as `readOnly`.
23
+ */
24
+ filter?: 'auto' | 'manual' | 'off';
20
25
  }
21
26
  /**
22
27
  * Injected framework-specific components for ComboboxInput rendering.
@@ -2,14 +2,22 @@ import type { ComboboxCallbacks, ComboboxHandle } from './types';
2
2
  /** Options for configuring the input-mode combobox controller. */
3
3
  export interface SetupComboboxInputOptions extends ComboboxCallbacks {
4
4
  /**
5
- * When true (default), the combobox automatically filters options as the user types.
6
- * Each registered `Combobox.Option` receives filter state updates and hides itself
7
- * when it does not match the current input value.
5
+ * Controls how the combobox filters options as the user types.
8
6
  *
9
- * Set to false when you want to handle filtering yourself (e.g. async search,
10
- * consumer-side pre-filtering). Options will not be registered for auto-filtering.
7
+ * - `'auto'` (default) Options are automatically filtered client-side.
8
+ * - `'manual'` Filtering is the consumer's responsibility.
9
+ * - `'off'` — Like `'manual'`, and `openOnFocus` defaults to `true`.
10
+ * The core template renders the input as `readOnly`.
11
11
  */
12
- autoFilter?: boolean;
12
+ filter?: 'auto' | 'manual' | 'off';
13
+ /**
14
+ * When true, the combobox opens automatically when the input receives focus.
15
+ * When false (default, unless `filter` is `'off'`), the combobox only opens
16
+ * on click, typing, or keyboard navigation.
17
+ *
18
+ * @default false (true when filter is 'off')
19
+ */
20
+ openOnFocus?: boolean;
13
21
  }
14
22
  /**
15
23
  * Set up a combobox with an input trigger (autocomplete/filter pattern).
package/lumx.css CHANGED
@@ -5669,21 +5669,10 @@ table {
5669
5669
  /* Selection Chip group
5670
5670
  ========================================================================== */
5671
5671
  .lumx-selection-chip-group {
5672
- max-width: 100%;
5673
- }
5674
- .lumx-selection-chip-group:empty {
5675
- display: none;
5676
- }
5677
- .lumx-selection-chip-group__item {
5678
- display: flex;
5679
- overflow: hidden;
5672
+ align-content: flex-start;
5680
5673
  }
5681
- .lumx-selection-chip-group__chip {
5682
- overflow: hidden;
5683
- }
5684
- .lumx-selection-chip-group__chip .lumx-chip__label {
5685
- overflow: hidden;
5686
- text-overflow: ellipsis;
5674
+ .lumx-selection-chip-group, .lumx-selection-chip-group .lumx-chip, .lumx-selection-chip-group .lumx-chip__label {
5675
+ min-width: 0;
5687
5676
  }
5688
5677
 
5689
5678
  /* ==========================================================================
@@ -5701,6 +5690,22 @@ table {
5701
5690
  }
5702
5691
  .lumx-combobox-popover__scroll {
5703
5692
  overflow-y: auto;
5693
+ scroll-snap-type: y proximity;
5694
+ }
5695
+ @media (prefers-reduced-motion: no-preference) {
5696
+ .lumx-combobox-popover__scroll {
5697
+ scroll-behavior: smooth;
5698
+ }
5699
+ }
5700
+ .lumx-combobox-popover__scroll::before {
5701
+ content: "";
5702
+ display: block;
5703
+ scroll-snap-align: start;
5704
+ }
5705
+ .lumx-combobox-popover__scroll::after {
5706
+ content: "";
5707
+ display: block;
5708
+ scroll-snap-align: end;
5704
5709
  }
5705
5710
 
5706
5711
  .lumx-combobox-popover:empty, .lumx-combobox-popover:not(:has(.lumx-combobox-option)):not(:has(.lumx-combobox-state)):not(:has(.lumx-combobox-option-skeleton)),
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "dependencies": {
9
9
  "@floating-ui/dom": "^1.7.5",
10
- "@lumx/icons": "^4.11.0-next.5",
10
+ "@lumx/icons": "^4.11.0-next.7",
11
11
  "classnames": "^2.3.2",
12
12
  "focus-visible": "^5.0.2",
13
13
  "lodash": "4.18.1",
@@ -69,7 +69,7 @@
69
69
  "update-version-changelog": "yarn version-changelog ../../CHANGELOG.md"
70
70
  },
71
71
  "sideEffects": false,
72
- "version": "4.11.0-next.5",
72
+ "version": "4.11.0-next.7",
73
73
  "devDependencies": {
74
74
  "@rollup/plugin-typescript": "^12.3.0",
75
75
  "@testing-library/dom": "^10.4.1",
@@ -191,23 +191,10 @@
191
191
  ========================================================================== */
192
192
 
193
193
  .#{$lumx-base-prefix}-selection-chip-group {
194
- max-width: 100%;
194
+ align-content: flex-start;
195
195
 
196
- &:empty {
197
- display: none;
198
- }
199
-
200
- &__item {
201
- display: flex;
202
- overflow: hidden;
203
- }
204
-
205
- &__chip {
206
- overflow: hidden;
207
-
208
- .#{$lumx-base-prefix}-chip__label {
209
- overflow: hidden;
210
- text-overflow: ellipsis;
196
+ // Shrink chips in constrained space
197
+ &, & .#{$lumx-base-prefix}-chip, & .#{$lumx-base-prefix}-chip__label {
198
+ min-width: 0;
211
199
  }
212
- }
213
200
  }
@@ -18,6 +18,21 @@
18
18
 
19
19
  &__scroll {
20
20
  overflow-y: auto;
21
+ scroll-snap-type: y proximity;
22
+ @media (prefers-reduced-motion: no-preference) {
23
+ scroll-behavior: smooth;
24
+ }
25
+
26
+ &::before {
27
+ content: '';
28
+ display: block;
29
+ scroll-snap-align: start;
30
+ }
31
+ &::after {
32
+ content: '';
33
+ display: block;
34
+ scroll-snap-align: end;
35
+ }
21
36
  }
22
37
  }
23
38