@q1travel/design-system 0.5.1 → 0.6.1

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.
@@ -20,7 +20,13 @@ New recommended code examples and product migrations use only the canonical API.
20
20
 
21
21
  When a canonical prop and its deprecated alias are both defined, the canonical prop wins. Resolution uses nullish precedence, so `svgOnly={false}` still overrides `iconOnly={true}`, and a defined `aria-label` still overrides `ariaLabel`.
22
22
 
23
- IconButton requires either `aria-label` or the deprecated `ariaLabel` at the TypeScript boundary. Its development warning evaluates the resolved accessible name.
23
+ IconButton requires either `aria-label` or the deprecated `ariaLabel` at the TypeScript boundary. Its built-package runtime warning evaluates the resolved accessible name so JavaScript consumers retain the same guard after package build.
24
+
25
+ ## Native Button Props
26
+
27
+ Button and IconButton accept native button props, ARIA attributes, `data-*` attributes, and DOM event handlers. `data-*` values accept React-renderable scalar metadata (`string`, `number`, `boolean`, `null`, or `undefined`); `null` and `undefined` omit the attribute. They forward those props to the real `<button>` instead of a wrapper so menu semantics, roving focus, hover, and pointer-down behavior remain attached to the interactive element.
28
+
29
+ Package-owned semantics are applied after native props. `type`, `className`, `disabled`, loading `aria-disabled`/`tabIndex`, the resolved accessible name, `ref`, and the loading click guard therefore keep their documented behavior. Outside loading, a consumer-provided `tabIndex` or `aria-disabled` remains intact. The canonical native `aria-keyshortcuts` value wins over the compatibility `ariaKeyshortcuts` field by nullish precedence.
24
30
 
25
31
  ## Component-Owned Semantics
26
32
 
@@ -43,6 +49,9 @@ The scan covers the current local checkouts named below; it is not evidence abou
43
49
 
44
50
  - `npm run check` verifies the documentation build, source contracts, and real-browser behavior.
45
51
  - `npm run build:pkg` builds the package and verifies emitted declarations, consumer type compatibility, and package runtime behavior.
52
+ - The package API gate renders the built package, not source modules, so it proves native-prop passthrough and the JavaScript accessible-name warning survive publication build transforms.
53
+ - The clean-tarball consumer gate installs the generated tarball in an isolated consumer, imports Button and IconButton from that installed package, and executes loading/native-prop and JavaScript accessible-name contracts against the installed runtime.
54
+ - The browser menu-ARIA passthrough proof uses a hidden, non-navigation fixture rendered by the real components. Public specimens must not claim popup semantics without implementing the corresponding interaction.
46
55
  - Both gates are required for this migration. Neither gate publishes a package.
47
56
 
48
57
  ## Removal Conditions
@@ -61,3 +70,4 @@ Until then, the aliases remain tested public compatibility contracts.
61
70
  - This contract does not migrate `q1travel-web`.
62
71
  - This contract does not choose a package version, publish a package, or remove an alias.
63
72
  - This contract does not change Button size, loading, variant, route, or styling contracts beyond the decorative slot boundary described above.
73
+ - This contract does not move button semantics or event handlers to a wrapper.
@@ -1,4 +1,6 @@
1
1
  import { AnchorHTMLAttributes } from 'react';
2
+ import { ButtonHTMLAttributes } from 'react';
3
+ import { ComponentPropsWithoutRef } from 'react';
2
4
  import { FocusEventHandler } from 'react';
3
5
  import { HTMLAttributes } from 'react';
4
6
  import { InputHTMLAttributes } from 'react';
@@ -239,11 +241,8 @@ export declare type ButtonLinkProps = Omit<ButtonBaseProps, 'type'> & {
239
241
  ref?: Ref<HTMLAnchorElement>;
240
242
  };
241
243
 
242
- declare type ButtonProps = ButtonBaseProps & {
243
- onClick?: MouseEventHandler<HTMLButtonElement>;
244
- onFocus?: FocusEventHandler<HTMLButtonElement>;
245
- onBlur?: FocusEventHandler<HTMLButtonElement>;
246
- onKeyDown?: KeyboardEventHandler<HTMLButtonElement>;
244
+ declare type ButtonProps = ButtonBaseProps & Omit<ComponentPropsWithoutRef<'button'>, keyof ButtonBaseProps> & {
245
+ [dataAttribute: `data-${string}`]: string | number | boolean | null | undefined;
247
246
  /** 供 focus 管理、测量、浮层定位等场景使用。 */
248
247
  ref?: Ref<HTMLButtonElement>;
249
248
  };
@@ -521,6 +520,54 @@ export declare type ContextMenuEntry = {
521
520
  type: 'separator';
522
521
  };
523
522
 
523
+ export declare function ContextSwitcher({ currentContext, groups, open, defaultOpen, onOpenChange, onSelect, pendingId, errorMessage, footerActions, onFooterAction, label, }: ContextSwitcherProps): JSX.Element;
524
+
525
+ export declare type ContextSwitcherAction = {
526
+ id: string;
527
+ label: ReactNode;
528
+ textValue: string;
529
+ icon?: ReactNode;
530
+ disabled?: boolean;
531
+ };
532
+
533
+ export declare type ContextSwitcherCurrent = {
534
+ label: ReactNode;
535
+ description?: ReactNode;
536
+ avatar?: ReactNode;
537
+ textValue: string;
538
+ };
539
+
540
+ export declare type ContextSwitcherGroup = {
541
+ id: string;
542
+ label: ReactNode;
543
+ textValue: string;
544
+ selectedId?: string;
545
+ items: ContextSwitcherItem[];
546
+ };
547
+
548
+ export declare type ContextSwitcherItem = {
549
+ id: string;
550
+ label: ReactNode;
551
+ textValue: string;
552
+ description?: ReactNode;
553
+ avatar?: ReactNode;
554
+ disabled?: boolean;
555
+ };
556
+
557
+ export declare type ContextSwitcherProps = {
558
+ currentContext: ContextSwitcherCurrent;
559
+ groups: ContextSwitcherGroup[];
560
+ open?: boolean;
561
+ defaultOpen?: boolean;
562
+ onOpenChange?: (open: boolean) => void;
563
+ onSelect: (item: ContextSwitcherItem) => void;
564
+ pendingId?: string;
565
+ errorMessage?: ReactNode;
566
+ footerActions?: ContextSwitcherAction[];
567
+ onFooterAction?: (action: ContextSwitcherAction) => void;
568
+ label?: string;
569
+ };
570
+
524
571
  export declare function ControlOption({ id, label, description, error, indeterminate, ref, type, ...rest }: ControlOptionOwnProps & (FieldShellProps | FieldBareProps) & CheckboxOnlyProps & {
525
572
  type: 'checkbox' | 'radio';
526
573
  } & NativeInputProps): JSX.Element;
@@ -707,7 +754,7 @@ declare type IconButtonAccessibleName = {
707
754
  ariaLabel: string;
708
755
  };
709
756
 
710
- export declare type IconButtonProps = IconButtonAccessibleName & {
757
+ declare type IconButtonBaseProps = {
711
758
  variant?: ButtonVariant;
712
759
  size?: ButtonSize;
713
760
  circle?: boolean;
@@ -717,11 +764,10 @@ export declare type IconButtonProps = IconButtonAccessibleName & {
717
764
  type?: 'button' | 'submit' | 'reset';
718
765
  className?: string;
719
766
  children?: ReactNode;
720
- onClick?: MouseEventHandler<HTMLButtonElement>;
721
- 'aria-describedby'?: string;
722
- onFocus?: FocusEventHandler<HTMLButtonElement>;
723
- onBlur?: FocusEventHandler<HTMLButtonElement>;
724
- onKeyDown?: KeyboardEventHandler<HTMLButtonElement>;
767
+ };
768
+
769
+ export declare type IconButtonProps = IconButtonAccessibleName & IconButtonBaseProps & Omit<ComponentPropsWithoutRef<'button'>, keyof IconButtonBaseProps | 'aria-label'> & {
770
+ [dataAttribute: `data-${string}`]: string | number | boolean | null | undefined;
725
771
  ref?: Ref<HTMLButtonElement>;
726
772
  };
727
773
 
@@ -840,6 +886,74 @@ declare type NativeInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'id'
840
886
 
841
887
  declare type NativeInputProps_2 = Omit<InputHTMLAttributes<HTMLInputElement>, 'type'>;
842
888
 
889
+ export declare function Navigation({ className, ...props }: NavigationProps): JSX.Element;
890
+
891
+ export declare function NavigationGroup({ label, icon, expanded, defaultExpanded, onExpandedChange, children, }: NavigationGroupProps): JSX.Element;
892
+
893
+ export declare type NavigationGroupProps = {
894
+ label: ReactNode;
895
+ icon?: ReactNode;
896
+ expanded?: boolean;
897
+ defaultExpanded?: boolean;
898
+ onExpandedChange?: (expanded: boolean) => void;
899
+ children: ReactNode;
900
+ };
901
+
902
+ export declare function NavigationItem(props: NavigationItemProps): JSX.Element;
903
+
904
+ export declare type NavigationItemAsButton = NavigationItemOwnProps & {
905
+ href?: undefined;
906
+ } & Omit<ButtonHTMLAttributes<HTMLButtonElement>, keyof NavigationItemOwnProps>;
907
+
908
+ export declare type NavigationItemAsLink = NavigationItemOwnProps & {
909
+ href: string;
910
+ } & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof NavigationItemOwnProps | 'href'>;
911
+
912
+ declare type NavigationItemOwnProps = {
913
+ active?: boolean;
914
+ disabled?: boolean;
915
+ icon?: ReactNode;
916
+ badge?: ReactNode;
917
+ description?: ReactNode;
918
+ action?: ReactNode;
919
+ children: ReactNode;
920
+ className?: string;
921
+ };
922
+
923
+ export declare type NavigationItemProps = NavigationItemAsLink | NavigationItemAsButton;
924
+
925
+ export declare type NavigationProps = HTMLAttributes<HTMLElement> & {
926
+ 'aria-label': string;
927
+ };
928
+
929
+ export declare function NavigationSection({ label, action, children, className, ...props }: NavigationSectionProps): JSX.Element;
930
+
931
+ declare type NavigationSectionLabel = Exclude<ReactNode, boolean | null | undefined>;
932
+
933
+ declare type NavigationSectionNativeProps = Omit<HTMLAttributes<HTMLElement>, keyof NavigationSectionOwnProps>;
934
+
935
+ declare type NavigationSectionOwnProps = {
936
+ label?: ReactNode;
937
+ action?: ReactNode;
938
+ children: ReactNode;
939
+ className?: string;
940
+ };
941
+
942
+ export declare type NavigationSectionProps = NavigationSectionWithLabel | NavigationSectionWithAccessibleName;
943
+
944
+ declare type NavigationSectionWithAccessibleName = NavigationSectionNativeProps & Omit<NavigationSectionOwnProps, 'action'> & {
945
+ label?: undefined;
946
+ action?: never;
947
+ } & ({
948
+ 'aria-label': string;
949
+ } | {
950
+ 'aria-labelledby': string;
951
+ });
952
+
953
+ declare type NavigationSectionWithLabel = NavigationSectionNativeProps & Omit<NavigationSectionOwnProps, 'label'> & {
954
+ label: NavigationSectionLabel;
955
+ };
956
+
843
957
  export declare function Note({ tone, size, filled, disabled, label, action, children, }: {
844
958
  tone?: NoteTone;
845
959
  size?: NoteSize;
@@ -1015,6 +1129,26 @@ export declare function ShowMore({ items, initial, noBorder, initialExpanded, }:
1015
1129
  initialExpanded?: boolean;
1016
1130
  }): JSX.Element;
1017
1131
 
1132
+ export declare const Sidebar: typeof SidebarRoot & {
1133
+ Header: typeof SidebarHeader;
1134
+ Content: typeof SidebarContent;
1135
+ Footer: typeof SidebarFooter;
1136
+ };
1137
+
1138
+ declare function SidebarContent({ className, ...props }: SidebarSlotProps): JSX.Element;
1139
+
1140
+ declare function SidebarFooter({ className, ...props }: SidebarSlotProps): JSX.Element;
1141
+
1142
+ declare function SidebarHeader({ className, ...props }: SidebarSlotProps): JSX.Element;
1143
+
1144
+ export declare type SidebarProps = HTMLAttributes<HTMLElement> & {
1145
+ 'aria-label': string;
1146
+ };
1147
+
1148
+ declare function SidebarRoot({ className, ...props }: SidebarProps): JSX.Element;
1149
+
1150
+ export declare type SidebarSlotProps = HTMLAttributes<HTMLDivElement>;
1151
+
1018
1152
  export declare function Skeleton({ shape, animated, show, className, children, }: {
1019
1153
  shape?: SkeletonShape;
1020
1154
  animated?: boolean;