tyrell-react 1.0.0-RC13 → 1.0.0-RC15

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.
Files changed (121) hide show
  1. package/dist/components/TyButton.d.ts +1 -1
  2. package/dist/components/TyButton.d.ts.map +1 -1
  3. package/dist/components/TyCalendar.d.ts +4 -3
  4. package/dist/components/TyCalendar.d.ts.map +1 -1
  5. package/dist/components/TyCalendar.js +4 -12
  6. package/dist/components/TyCalendar.js.map +1 -1
  7. package/dist/components/TyCalendarMonth.d.ts +1 -1
  8. package/dist/components/TyCalendarMonth.d.ts.map +1 -1
  9. package/dist/components/TyCalendarMonth.js +0 -5
  10. package/dist/components/TyCalendarMonth.js.map +1 -1
  11. package/dist/components/TyCalendarNavigation.d.ts.map +1 -1
  12. package/dist/components/TyCalendarNavigation.js +0 -5
  13. package/dist/components/TyCalendarNavigation.js.map +1 -1
  14. package/dist/components/TyCheckbox.d.ts +1 -1
  15. package/dist/components/TyCheckbox.d.ts.map +1 -1
  16. package/dist/components/TyCheckbox.js +0 -8
  17. package/dist/components/TyCheckbox.js.map +1 -1
  18. package/dist/components/TyCopy.d.ts +4 -2
  19. package/dist/components/TyCopy.d.ts.map +1 -1
  20. package/dist/components/TyCopy.js +4 -7
  21. package/dist/components/TyCopy.js.map +1 -1
  22. package/dist/components/TyDatePicker.d.ts +7 -3
  23. package/dist/components/TyDatePicker.d.ts.map +1 -1
  24. package/dist/components/TyDatePicker.js +6 -12
  25. package/dist/components/TyDatePicker.js.map +1 -1
  26. package/dist/components/TyFileUpload.d.ts.map +1 -1
  27. package/dist/components/TyFileUpload.js +0 -1
  28. package/dist/components/TyFileUpload.js.map +1 -1
  29. package/dist/components/TyIcon.d.ts.map +1 -1
  30. package/dist/components/TyIcon.js +0 -4
  31. package/dist/components/TyIcon.js.map +1 -1
  32. package/dist/components/TyInput.d.ts +4 -4
  33. package/dist/components/TyInput.d.ts.map +1 -1
  34. package/dist/components/TyInput.js +0 -10
  35. package/dist/components/TyInput.js.map +1 -1
  36. package/dist/components/TyModal.d.ts +16 -2
  37. package/dist/components/TyModal.d.ts.map +1 -1
  38. package/dist/components/TyModal.js +17 -17
  39. package/dist/components/TyModal.js.map +1 -1
  40. package/dist/components/TyOption.d.ts +1 -1
  41. package/dist/components/TyOption.d.ts.map +1 -1
  42. package/dist/components/TyOption.js +0 -2
  43. package/dist/components/TyOption.js.map +1 -1
  44. package/dist/components/TyPopup.d.ts +4 -2
  45. package/dist/components/TyPopup.d.ts.map +1 -1
  46. package/dist/components/TyPopup.js +2 -9
  47. package/dist/components/TyPopup.js.map +1 -1
  48. package/dist/components/TyRadio.d.ts +1 -1
  49. package/dist/components/TyRadio.d.ts.map +1 -1
  50. package/dist/components/TyRadioGroup.d.ts +1 -1
  51. package/dist/components/TyRadioGroup.d.ts.map +1 -1
  52. package/dist/components/TyResizeObserver.d.ts.map +1 -1
  53. package/dist/components/TyResizeObserver.js +0 -4
  54. package/dist/components/TyResizeObserver.js.map +1 -1
  55. package/dist/components/TyScrollContainer.d.ts.map +1 -1
  56. package/dist/components/TyScrollContainer.js +0 -6
  57. package/dist/components/TyScrollContainer.js.map +1 -1
  58. package/dist/components/TySelect.d.ts +13 -11
  59. package/dist/components/TySelect.d.ts.map +1 -1
  60. package/dist/components/TySelect.js +5 -12
  61. package/dist/components/TySelect.js.map +1 -1
  62. package/dist/components/TyStep.d.ts.map +1 -1
  63. package/dist/components/TyStep.js +0 -5
  64. package/dist/components/TyStep.js.map +1 -1
  65. package/dist/components/TySwitch.d.ts +1 -1
  66. package/dist/components/TySwitch.d.ts.map +1 -1
  67. package/dist/components/TyTab.d.ts.map +1 -1
  68. package/dist/components/TyTab.js +0 -6
  69. package/dist/components/TyTab.js.map +1 -1
  70. package/dist/components/TyTabs.d.ts +2 -0
  71. package/dist/components/TyTabs.d.ts.map +1 -1
  72. package/dist/components/TyTabs.js +4 -6
  73. package/dist/components/TyTabs.js.map +1 -1
  74. package/dist/components/TyTag.d.ts +1 -1
  75. package/dist/components/TyTag.d.ts.map +1 -1
  76. package/dist/components/TyTag.js +0 -2
  77. package/dist/components/TyTag.js.map +1 -1
  78. package/dist/components/TyTextarea.d.ts.map +1 -1
  79. package/dist/components/TyTextarea.js +0 -6
  80. package/dist/components/TyTextarea.js.map +1 -1
  81. package/dist/components/TyTooltip.d.ts +4 -3
  82. package/dist/components/TyTooltip.d.ts.map +1 -1
  83. package/dist/components/TyTooltip.js +0 -4
  84. package/dist/components/TyTooltip.js.map +1 -1
  85. package/dist/components/TyWizard.d.ts.map +1 -1
  86. package/dist/components/TyWizard.js +0 -5
  87. package/dist/components/TyWizard.js.map +1 -1
  88. package/dist/components/index.d.ts.map +1 -1
  89. package/dist/components/index.js +2 -62
  90. package/dist/components/index.js.map +1 -1
  91. package/dist/version.d.ts +1 -1
  92. package/dist/version.js +1 -1
  93. package/package.json +1 -1
  94. package/src/components/TyButton.tsx +1 -1
  95. package/src/components/TyCalendar.tsx +7 -15
  96. package/src/components/TyCalendarMonth.tsx +1 -7
  97. package/src/components/TyCalendarNavigation.tsx +0 -6
  98. package/src/components/TyCheckbox.tsx +1 -10
  99. package/src/components/TyCopy.tsx +8 -9
  100. package/src/components/TyDatePicker.tsx +20 -16
  101. package/src/components/TyFileUpload.tsx +0 -2
  102. package/src/components/TyIcon.tsx +0 -5
  103. package/src/components/TyInput.tsx +4 -16
  104. package/src/components/TyModal.tsx +36 -21
  105. package/src/components/TyOption.tsx +1 -4
  106. package/src/components/TyPopup.tsx +10 -13
  107. package/src/components/TyRadio.tsx +1 -1
  108. package/src/components/TyRadioGroup.tsx +1 -1
  109. package/src/components/TyResizeObserver.tsx +0 -5
  110. package/src/components/TyScrollContainer.tsx +0 -8
  111. package/src/components/TySelect.tsx +22 -24
  112. package/src/components/TyStep.tsx +0 -6
  113. package/src/components/TySwitch.tsx +1 -1
  114. package/src/components/TyTab.tsx +0 -7
  115. package/src/components/TyTabs.tsx +6 -6
  116. package/src/components/TyTag.tsx +1 -4
  117. package/src/components/TyTextarea.tsx +0 -8
  118. package/src/components/TyTooltip.tsx +8 -8
  119. package/src/components/TyWizard.tsx +0 -6
  120. package/src/components/index.ts +2 -97
  121. package/src/version.ts +1 -1
@@ -3,7 +3,6 @@ import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty, coerceBool } from '../utils/use-boolean-prop';
4
4
  import { needsPropertyBridge } from '../utils/react-version';
5
5
 
6
- // Event detail structure for modal events
7
6
  export interface TyModalEventDetail {
8
7
  reason?: 'programmatic' | 'native' | 'backdrop' | 'escape' | 'close-button';
9
8
  returnValue?: string;
@@ -19,7 +18,6 @@ export interface TyModalBeforeCloseDetail {
19
18
  reason: 'programmatic' | 'backdrop' | 'escape' | 'close-button' | 'native';
20
19
  }
21
20
 
22
- // Type definitions for Ty Modal component
23
21
  export interface TyModalProps extends React.HTMLAttributes<HTMLElement> {
24
22
  /** Controls modal visibility */
25
23
  open?: boolean;
@@ -27,12 +25,28 @@ export interface TyModalProps extends React.HTMLAttributes<HTMLElement> {
27
25
  /** Show backdrop behind modal (default: true) */
28
26
  backdrop?: boolean;
29
27
 
30
- /** Allow closing modal by clicking backdrop (default: true) */
28
+ /**
29
+ * @deprecated Use `preventOutsideClick` — string-boolean attrs are being
30
+ * phased out. Still works; prevent-* wins when both are set.
31
+ */
31
32
  closeOnOutsideClick?: boolean;
32
33
 
33
- /** Allow closing modal with Escape key (default: true) */
34
+ /**
35
+ * @deprecated Use `preventEscape` — string-boolean attrs are being phased
36
+ * out. Still works; prevent-* wins when both are set.
37
+ */
34
38
  closeOnEscape?: boolean;
35
39
 
40
+ /** Backdrop clicks no longer close the modal (also hides the built-in ✕) */
41
+ preventOutsideClick?: boolean;
42
+
43
+ /**
44
+ * ESC no longer closes the modal (keydown is consumed, so the browser's
45
+ * double-ESC anti-trap never fires). A fully guarded modal must render its
46
+ * own close control — WCAG 2.1.2.
47
+ */
48
+ preventEscape?: boolean;
49
+
36
50
  /**
37
51
  * Accessible name — sets aria-label on the internal <dialog>. The dialog
38
52
  * gets role="dialog" for free, but nothing names it unless you set this.
@@ -52,7 +66,6 @@ export interface TyModalProps extends React.HTMLAttributes<HTMLElement> {
52
66
  children?: React.ReactNode;
53
67
  }
54
68
 
55
- // Ref interface for imperative methods
56
69
  export interface TyModalRef {
57
70
  show: () => void;
58
71
  /**
@@ -64,13 +77,14 @@ export interface TyModalRef {
64
77
  element: HTMLElement | null;
65
78
  }
66
79
 
67
- // React wrapper for ty-modal web component
68
80
  export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
69
81
  ({
70
82
  open,
71
83
  backdrop,
72
84
  closeOnOutsideClick,
73
85
  closeOnEscape,
86
+ preventOutsideClick,
87
+ preventEscape,
74
88
  label,
75
89
  onOpen,
76
90
  onClose,
@@ -80,7 +94,6 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
80
94
  }, ref) => {
81
95
  const elementRef = useRef<HTMLElement>(null);
82
96
 
83
- // Expose imperative methods through ref
84
97
  useImperativeHandle(ref, () => ({
85
98
  show: () => {
86
99
  if (elementRef.current && typeof (elementRef.current as any).show === 'function') {
@@ -95,17 +108,12 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
95
108
  element: elementRef.current,
96
109
  }), []);
97
110
 
98
- // Handle modal events.
99
- //
100
- // ty-dropdown, ty-multiselect, ty-date-picker etc. dispatch their own
101
- // `open`/`close` custom events with `bubbles: true, composed: true` when
102
- // their internal popups toggle. Those events bubble up through the
103
- // modal's slotted content and land on the ty-modal host — same event
104
- // type, same listener. Without the `event.target === element` guard, an
105
- // `onClose={() => setIsOpen(false)}` callback would fire every time the
106
- // user closes a dropdown inside the modal, and the React state flip
107
- // would close the modal. Core's modal.ts already applies the same guard
108
- // on its internal <dialog>.onclose; this is the React-layer mirror.
111
+ // Popup lifecycle events (`open`/`close`, plus `beforeclose` on the modal)
112
+ // no longer bubble — core dispatches them non-composed on the element
113
+ // itself, like the native <dialog> events they mirror, so a dropdown or
114
+ // nested modal closing inside this one can't reach these listeners. The
115
+ // `event.target === element` guard stays as belt-and-braces for consumers
116
+ // pinned to an older tyrell-components.
109
117
  useEffect(() => {
110
118
  const element = elementRef.current;
111
119
  if (!element) return;
@@ -125,7 +133,6 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
125
133
  if (onBeforeClose) onBeforeClose(event);
126
134
  };
127
135
 
128
- // Listen for custom modal events
129
136
  if (onOpen) {
130
137
  element.addEventListener('open', handleOpen as EventListener);
131
138
  }
@@ -170,9 +177,10 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
170
177
  setIf('backdrop', backdrop);
171
178
  setIf('closeOnOutsideClick', closeOnOutsideClick);
172
179
  setIf('closeOnEscape', closeOnEscape);
173
- }, [backdrop, closeOnOutsideClick, closeOnEscape]);
180
+ setIf('preventOutsideClick', preventOutsideClick);
181
+ setIf('preventEscape', preventEscape);
182
+ }, [backdrop, closeOnOutsideClick, closeOnEscape, preventOutsideClick, preventEscape]);
174
183
 
175
- // Convert React props to web component attributes
176
184
  const webComponentProps: Record<string, any> = {
177
185
  ...hostProps(props),
178
186
  ref: elementRef,
@@ -191,6 +199,13 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
191
199
  if (closeOnEscape !== undefined && !coerceBool(closeOnEscape)) {
192
200
  webComponentProps['close-on-escape'] = 'false';
193
201
  }
202
+ // Presence booleans: render the bare attribute only when true
203
+ if (preventOutsideClick !== undefined && coerceBool(preventOutsideClick)) {
204
+ webComponentProps['prevent-outside-click'] = '';
205
+ }
206
+ if (preventEscape !== undefined && coerceBool(preventEscape)) {
207
+ webComponentProps['prevent-escape'] = '';
208
+ }
194
209
  if (label) webComponentProps.label = label;
195
210
 
196
211
  return React.createElement(
@@ -2,7 +2,6 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- // Type definitions for Ty Option component
6
5
  export interface TyOptionProps extends React.HTMLAttributes<HTMLElement> {
7
6
  value?: string;
8
7
 
@@ -14,7 +13,7 @@ export interface TyOptionProps extends React.HTMLAttributes<HTMLElement> {
14
13
  label?: string;
15
14
 
16
15
  /** Semantic flavor — carried onto ty-selected-options chips */
17
- flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral' | 'info';
16
+ flavor?: 'primary' | 'success' | 'danger' | 'warning' | 'neutral' | 'info';
18
17
 
19
18
  disabled?: boolean;
20
19
  selected?: boolean;
@@ -22,12 +21,10 @@ export interface TyOptionProps extends React.HTMLAttributes<HTMLElement> {
22
21
  children?: React.ReactNode;
23
22
  }
24
23
 
25
- // React wrapper for ty-option web component
26
24
  export const TyOption = React.forwardRef<HTMLElement, TyOptionProps>(
27
25
  ({ children, label, flavor, disabled, selected, hidden, ...props }, ref) => {
28
26
  const elementRef = useRef<HTMLElement>(null);
29
27
 
30
- // Handle ref forwarding
31
28
  useEffect(() => {
32
29
  if (ref && elementRef.current) {
33
30
  if (typeof ref === 'function') {
@@ -2,10 +2,15 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- // Type definitions for Ty Popup component
5
+ type Placement =
6
+ | 'top-start' | 'top' | 'top-end'
7
+ | 'right-start' | 'right' | 'right-end'
8
+ | 'bottom-start' | 'bottom' | 'bottom-end'
9
+ | 'left-start' | 'left' | 'left-end';
10
+
6
11
  export interface TyPopupProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onClose'> {
7
- /** Preferred placement of the popup relative to anchor parent: "top" | "bottom" | "left" | "right" */
8
- placement?: 'top' | 'bottom' | 'left' | 'right';
12
+ /** Preferred placement of the popup relative to anchor parent: a side plus an optional cross-axis alignment (e.g. "bottom-start") */
13
+ placement?: Placement;
9
14
 
10
15
  /** Distance offset from the anchor in pixels (default: 8) */
11
16
  offset?: number;
@@ -26,14 +31,12 @@ export interface TyPopupProps extends Omit<React.HTMLAttributes<HTMLElement>, 'o
26
31
  children?: React.ReactNode;
27
32
  }
28
33
 
29
- // Programmatic API for popup control
30
34
  export interface TyPopupElement extends HTMLElement {
31
35
  openPopup(): void;
32
36
  closePopup(): void;
33
37
  togglePopup(): void;
34
38
  }
35
39
 
36
- // React wrapper for ty-popup web component
37
40
  export const TyPopup = React.forwardRef<TyPopupElement, TyPopupProps>(
38
41
  ({
39
42
  placement,
@@ -47,7 +50,6 @@ export const TyPopup = React.forwardRef<TyPopupElement, TyPopupProps>(
47
50
  }, ref) => {
48
51
  const elementRef = useRef<TyPopupElement>(null);
49
52
 
50
- // Handle ref forwarding
51
53
  useEffect(() => {
52
54
  if (ref && elementRef.current) {
53
55
  if (typeof ref === 'function') {
@@ -58,11 +60,8 @@ export const TyPopup = React.forwardRef<TyPopupElement, TyPopupProps>(
58
60
  }
59
61
  }, [ref]);
60
62
 
61
- // Listen for popup open/close events.
62
- // Guard with `event.target === element` so bubbled open/close events
63
- // from popup-like descendants (ty-dropdown, ty-multiselect, ty-date-picker
64
- // when slotted inside this popup) don't fire the consumer's onOpen/onClose.
65
- // See TyModal.tsx for the same pattern + rationale.
63
+ // Listen for popup open/close events. See TyModal.tsx for why the
64
+ // `event.target === element` guard is still here.
66
65
  useEffect(() => {
67
66
  const element = elementRef.current;
68
67
  if (!element) return;
@@ -85,13 +84,11 @@ export const TyPopup = React.forwardRef<TyPopupElement, TyPopupProps>(
85
84
  };
86
85
  }, [onOpen, onClose]);
87
86
 
88
- // Convert React props to web component attributes
89
87
  const webComponentProps: Record<string, any> = {
90
88
  ...hostProps(props),
91
89
  ref: elementRef,
92
90
  };
93
91
 
94
- // Add optional attributes only if they have values
95
92
  if (placement) {
96
93
  webComponentProps.placement = placement;
97
94
  }
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
5
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
6
6
  type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
7
7
 
8
8
  export interface TyRadioProps extends React.HTMLAttributes<HTMLElement> {
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
5
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
6
6
  type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
7
7
 
8
8
  export interface TyRadioGroupProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onInput'> {
@@ -1,7 +1,6 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
 
4
- // Type definitions for Ty ResizeObserver component
5
4
  export interface TyResizeObserverProps extends React.HTMLAttributes<HTMLElement> {
6
5
  /** Required unique identifier for size registry */
7
6
  id: string;
@@ -13,7 +12,6 @@ export interface TyResizeObserverProps extends React.HTMLAttributes<HTMLElement>
13
12
  children?: React.ReactNode;
14
13
  }
15
14
 
16
- // React wrapper for ty-resize-observer web component
17
15
  export const TyResizeObserver = React.forwardRef<HTMLElement, TyResizeObserverProps>(
18
16
  ({
19
17
  children,
@@ -23,7 +21,6 @@ export const TyResizeObserver = React.forwardRef<HTMLElement, TyResizeObserverPr
23
21
  }, ref) => {
24
22
  const elementRef = useRef<HTMLElement>(null);
25
23
 
26
- // Combine refs if needed
27
24
  useEffect(() => {
28
25
  if (ref && elementRef.current) {
29
26
  if (typeof ref === 'function') {
@@ -34,14 +31,12 @@ export const TyResizeObserver = React.forwardRef<HTMLElement, TyResizeObserverPr
34
31
  }
35
32
  }, [ref]);
36
33
 
37
- // Convert React props to web component attributes
38
34
  const webComponentProps: Record<string, any> = {
39
35
  ...hostProps(props),
40
36
  ref: elementRef,
41
37
  id,
42
38
  };
43
39
 
44
- // Add number attributes
45
40
  if (debounce !== undefined) webComponentProps.debounce = debounce;
46
41
 
47
42
  return React.createElement(
@@ -11,7 +11,6 @@ export interface TyScrollNearEdgeDetail {
11
11
  clientHeight: number;
12
12
  }
13
13
 
14
- // Type definitions for Ty ScrollContainer component
15
14
  export interface TyScrollContainerProps extends React.HTMLAttributes<HTMLElement> {
16
15
  /** Maximum height of the scroll container */
17
16
  maxHeight?: string;
@@ -44,7 +43,6 @@ export interface TyScrollContainerProps extends React.HTMLAttributes<HTMLElement
44
43
  children?: React.ReactNode;
45
44
  }
46
45
 
47
- // Ref interface for imperative methods
48
46
  export interface TyScrollContainerRef {
49
47
  /** Force update shadows (useful after dynamic content changes) */
50
48
  updateShadows: () => void;
@@ -64,7 +62,6 @@ export interface TyScrollContainerRef {
64
62
  element: HTMLElement | null;
65
63
  }
66
64
 
67
- // React wrapper for ty-scroll-container web component
68
65
  export const TyScrollContainer = React.forwardRef<TyScrollContainerRef, TyScrollContainerProps>(
69
66
  ({
70
67
  children,
@@ -81,7 +78,6 @@ export const TyScrollContainer = React.forwardRef<TyScrollContainerRef, TyScroll
81
78
  }, ref) => {
82
79
  const elementRef = useRef<HTMLElement>(null);
83
80
 
84
- // Expose imperative methods via ref
85
81
  useImperativeHandle(ref, () => ({
86
82
  updateShadows: () => { (elementRef.current as any)?.updateShadows?.(); },
87
83
  scrollToTop: (smooth = true) => { (elementRef.current as any)?.scrollToTop?.(smooth); },
@@ -109,7 +105,6 @@ export const TyScrollContainer = React.forwardRef<TyScrollContainerRef, TyScroll
109
105
  const isOverflowX = useBooleanProperty(elementRef, 'overflowX', overflowX);
110
106
  const isScrollAnchoring = useBooleanProperty(elementRef, 'scrollAnchoring', scrollAnchoring);
111
107
 
112
- // Custom events → React callbacks
113
108
  useEffect(() => {
114
109
  const el = elementRef.current;
115
110
  if (!el) return;
@@ -125,17 +120,14 @@ export const TyScrollContainer = React.forwardRef<TyScrollContainerRef, TyScroll
125
120
  return () => bound.forEach(([n, h]) => el.removeEventListener(n, h));
126
121
  }, [onNearEnd, onNearStart]);
127
122
 
128
- // Convert React props to web component attributes
129
123
  const webComponentProps: Record<string, any> = {
130
124
  ...hostProps(props),
131
125
  ref: elementRef,
132
126
  };
133
127
 
134
- // String attributes
135
128
  if (maxHeight) webComponentProps['max-height'] = maxHeight;
136
129
  if (nearEdgeThreshold != null) webComponentProps['near-edge-threshold'] = String(nearEdgeThreshold);
137
130
 
138
- // Boolean attributes
139
131
  if (shadow !== undefined && !coerceBool(shadow)) webComponentProps.shadow = 'false';
140
132
  if (isHideScrollbar) webComponentProps['hide-scrollbar'] = '';
141
133
  if (isCustomScrollbar) webComponentProps['custom-scrollbar'] = '';
@@ -3,10 +3,14 @@ import { hostProps } from '../utils/host-props';
3
3
  import { needsPropertyBridge } from '../utils/react-version';
4
4
  import { useBooleanProperty } from '../utils/use-boolean-prop';
5
5
 
6
- type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
6
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
7
7
  type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
8
+ type Placement =
9
+ | 'top-start' | 'top' | 'top-end'
10
+ | 'right-start' | 'right' | 'right-end'
11
+ | 'bottom-start' | 'bottom' | 'bottom-end'
12
+ | 'left-start' | 'left' | 'left-end';
8
13
 
9
- // Type definitions for Ty Select component
10
14
  export interface TySelectItem {
11
15
  value: string;
12
16
  label: string;
@@ -56,11 +60,10 @@ export interface TySelectProps extends Omit<React.HTMLAttributes<HTMLElement>, '
56
60
  /** Mark the field as required */
57
61
  required?: boolean;
58
62
 
59
- /**
60
- * Search row visibility: 'auto' (default) shows it only for 8+ options,
61
- * 'always' / 'never' force it. external-search always shows it.
62
- */
63
- searchable?: 'auto' | 'always' | 'never' | boolean;
63
+ /** Drop the popup search row. A select is searchable by default; this is
64
+ * the single opt-out. Cannot override externalSearch/allowCreate, where
65
+ * the input is the only way to get a query out. */
66
+ notSearchable?: boolean;
64
67
 
65
68
  /**
66
69
  * External (remote) search mode — the component stops filtering and emits
@@ -89,12 +92,15 @@ export interface TySelectProps extends Omit<React.HTMLAttributes<HTMLElement>, '
89
92
  /** Loading state — shows a spinner in the options area (external search in flight) */
90
93
  loading?: boolean;
91
94
 
92
- /** Size variant */
93
- /** Field size fields come in exactly three; legacy xs/xl map to sm/lg */
94
- size?: 'sm' | 'md' | 'lg';
95
+ /** Field size — the ladder shared by every field component
96
+ * (styles/field-size.ts). Defaults to 'sm'. */
97
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
98
+
99
+ /** Horizontal popup anchor: "start" (default, trigger's left edge), "center", or "end" (trigger's right edge) — clamped into the viewport either way. Useful with a custom slot="trigger" element. Ignored when `placement` is set. */
100
+ align?: 'start' | 'center' | 'end';
95
101
 
96
- /** Horizontal popup anchor: "start" (default, trigger's left edge) or "end" (trigger's right edge) clamped into the viewport either way. Useful with a custom slot="trigger" element. */
97
- align?: 'start' | 'end';
102
+ /** Full placement, same vocabulary as ty-popup/ty-tooltip: a side plus an optional cross-axis alignment (e.g. "bottom-end"). Takes precedence over `align` when set. */
103
+ placement?: Placement;
98
104
 
99
105
  /** Built-in x clear button in the default/compact trigger, shown once something is selected. Default true. Not shown with slot="trigger" — use the ref's clear() method there instead. */
100
106
  clearable?: boolean;
@@ -126,7 +132,6 @@ export interface TySelectElement extends HTMLElement {
126
132
  clear(): void;
127
133
  }
128
134
 
129
- // React wrapper for ty-select web component
130
135
  export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
131
136
  ({
132
137
  value,
@@ -138,7 +143,7 @@ export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
138
143
  disabled,
139
144
  readonly,
140
145
  required,
141
- searchable,
146
+ notSearchable,
142
147
  externalSearch,
143
148
  debounce,
144
149
  allowCreate,
@@ -146,6 +151,7 @@ export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
146
151
  loading,
147
152
  size,
148
153
  align,
154
+ placement,
149
155
  clearable,
150
156
  flavor,
151
157
  onChange,
@@ -158,7 +164,6 @@ export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
158
164
  }, ref) => {
159
165
  const elementRef = useRef<TySelectElement>(null);
160
166
 
161
- // Handle ref forwarding
162
167
  useEffect(() => {
163
168
  if (ref && elementRef.current) {
164
169
  if (typeof ref === 'function') {
@@ -181,7 +186,6 @@ export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
181
186
  }
182
187
  }, [value]);
183
188
 
184
- // Handle events
185
189
  const handleChange = useCallback((event: Event) => {
186
190
  if (onChange) onChange(event as CustomEvent<TySelectEventDetail>);
187
191
  }, [onChange]);
@@ -196,7 +200,6 @@ export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
196
200
  if (onCreate) onCreate(event as CustomEvent<{ value: string; label: string }>);
197
201
  }, [onCreate]);
198
202
 
199
- // Set up event listeners
200
203
  useEffect(() => {
201
204
  const element = elementRef.current;
202
205
  if (!element) return;
@@ -227,13 +230,11 @@ export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
227
230
  const isAllowCreate = useBooleanProperty(elementRef, 'allowCreate', allowCreate);
228
231
  const isClearable = useBooleanProperty(elementRef, 'clearable', clearable);
229
232
 
230
- // Convert React props to web component attributes
231
233
  const webComponentProps: Record<string, any> = {
232
234
  ...hostProps(props),
233
235
  ref: elementRef,
234
236
  };
235
237
 
236
- // Handle value conversion (array to comma-separated string)
237
238
  if (value !== undefined) {
238
239
  webComponentProps.value = Array.isArray(value) ? value.join(',') : value;
239
240
  }
@@ -252,13 +253,12 @@ export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
252
253
  if (name) webComponentProps.name = name;
253
254
  if (size) webComponentProps.size = size;
254
255
  if (align) webComponentProps.align = align;
256
+ if (placement) webComponentProps.placement = placement;
255
257
  if (isClearable) webComponentProps.clearable = '';
256
258
  if (flavor) webComponentProps.flavor = flavor;
257
259
  if (debounce !== undefined) webComponentProps.debounce = debounce.toString();
258
260
  if (createTransform) webComponentProps['create-transform'] = createTransform;
259
- if (searchable === 'always' || searchable === true) webComponentProps.searchable = 'true';
260
- else if (searchable === 'never' || searchable === false) webComponentProps.searchable = 'false';
261
- // 'auto' / undefined → omit (component default)
261
+ if (notSearchable) webComponentProps['not-searchable'] = '';
262
262
 
263
263
  return React.createElement('ty-select', webComponentProps, children);
264
264
  }
@@ -266,11 +266,9 @@ export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
266
266
 
267
267
  TySelect.displayName = 'TySelect';
268
268
 
269
- // ============================================================================
270
269
  // TySelectedOptions — out-of-band chip display for a TySelect
271
270
  // (ty-selected-tags below is the same element under its original tag name,
272
271
  // kept for backward compatibility.)
273
- // ============================================================================
274
272
 
275
273
  export interface TySelectedTagsProps extends React.HTMLAttributes<HTMLElement> {
276
274
  /** id of the ty-select to display. Falls back to the previous element sibling. */
@@ -1,7 +1,6 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
 
4
- // Type definitions for Ty Step component
5
4
  export interface TyStepProps extends React.HTMLAttributes<HTMLElement> {
6
5
  /** Required unique identifier for the step */
7
6
  id: string;
@@ -22,7 +21,6 @@ export interface TyStepProps extends React.HTMLAttributes<HTMLElement> {
22
21
  children?: React.ReactNode;
23
22
  }
24
23
 
25
- // React wrapper for ty-step web component
26
24
  export const TyStep = React.forwardRef<HTMLElement, TyStepProps>(
27
25
  ({
28
26
  children,
@@ -35,7 +33,6 @@ export const TyStep = React.forwardRef<HTMLElement, TyStepProps>(
35
33
  }, ref) => {
36
34
  const elementRef = useRef<HTMLElement>(null);
37
35
 
38
- // Combine refs if needed
39
36
  useEffect(() => {
40
37
  if (ref && elementRef.current) {
41
38
  if (typeof ref === 'function') {
@@ -46,19 +43,16 @@ export const TyStep = React.forwardRef<HTMLElement, TyStepProps>(
46
43
  }
47
44
  }, [ref]);
48
45
 
49
- // Convert React props to web component attributes
50
46
  const webComponentProps: Record<string, any> = {
51
47
  ...hostProps(props),
52
48
  ref: elementRef,
53
49
  id,
54
50
  };
55
51
 
56
- // Add string attributes
57
52
  if (label) webComponentProps.label = label;
58
53
  if (description) webComponentProps.description = description;
59
54
  if (status) webComponentProps.status = status;
60
55
 
61
- // Add boolean attributes
62
56
  if (disabled) webComponentProps.disabled = true;
63
57
 
64
58
  return React.createElement(
@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
5
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
6
6
  type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
7
7
 
8
8
  export interface TySwitchProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onInput'> {
@@ -2,7 +2,6 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- // Type definitions for Ty Tab component
6
5
  export interface TyTabProps extends React.HTMLAttributes<HTMLElement> {
7
6
  /** Required unique identifier */
8
7
  id: string;
@@ -17,7 +16,6 @@ export interface TyTabProps extends React.HTMLAttributes<HTMLElement> {
17
16
  children?: React.ReactNode;
18
17
  }
19
18
 
20
- // React wrapper for ty-tab web component
21
19
  export const TyTab = React.forwardRef<HTMLElement, TyTabProps>(
22
20
  ({
23
21
  children,
@@ -28,7 +26,6 @@ export const TyTab = React.forwardRef<HTMLElement, TyTabProps>(
28
26
  }, ref) => {
29
27
  const elementRef = useRef<HTMLElement>(null);
30
28
 
31
- // Combine refs if needed
32
29
  useEffect(() => {
33
30
  if (ref && elementRef.current) {
34
31
  if (typeof ref === 'function') {
@@ -39,20 +36,16 @@ export const TyTab = React.forwardRef<HTMLElement, TyTabProps>(
39
36
  }
40
37
  }, [ref]);
41
38
 
42
- // Convert React props to web component attributes
43
39
  const webComponentProps: Record<string, any> = {
44
40
  ...hostProps(props),
45
41
  ref: elementRef,
46
42
  };
47
43
 
48
- // Add required attribute
49
44
  webComponentProps.id = id;
50
45
 
51
- // Add boolean attributes
52
46
  const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled);
53
47
  if (isDisabled) webComponentProps.disabled = '';
54
48
 
55
- // Add string attributes
56
49
  if (label) webComponentProps.label = label;
57
50
 
58
51
  return React.createElement(
@@ -1,7 +1,6 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
 
4
- // Type definitions for Ty Tabs component
5
4
  export interface TyTabsProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
6
5
  /** Content area width (accepts px or %) */
7
6
  width?: string;
@@ -15,6 +14,9 @@ export interface TyTabsProps extends Omit<React.HTMLAttributes<HTMLElement>, 'on
15
14
  /** Position of tab buttons */
16
15
  placement?: 'top' | 'bottom';
17
16
 
17
+ /** Divide the bar equally between the tabs instead of scrolling them */
18
+ fixed?: boolean;
19
+
18
20
  /** Tab change event handler */
19
21
  onChange?: (event: CustomEvent<TabChangeDetail>) => void;
20
22
 
@@ -29,7 +31,6 @@ export interface TabChangeDetail {
29
31
  previousIndex: number | null;
30
32
  }
31
33
 
32
- // React wrapper for ty-tabs web component
33
34
  export const TyTabs = React.forwardRef<HTMLElement, TyTabsProps>(
34
35
  ({
35
36
  children,
@@ -37,12 +38,12 @@ export const TyTabs = React.forwardRef<HTMLElement, TyTabsProps>(
37
38
  height,
38
39
  active,
39
40
  placement,
41
+ fixed,
40
42
  onChange,
41
43
  ...props
42
44
  }, ref) => {
43
45
  const elementRef = useRef<HTMLElement>(null);
44
46
 
45
- // Handle change events
46
47
  useEffect(() => {
47
48
  const element = elementRef.current;
48
49
  if (!element) return;
@@ -60,7 +61,6 @@ export const TyTabs = React.forwardRef<HTMLElement, TyTabsProps>(
60
61
  };
61
62
  }, [onChange]);
62
63
 
63
- // Combine refs if needed
64
64
  useEffect(() => {
65
65
  if (ref && elementRef.current) {
66
66
  if (typeof ref === 'function') {
@@ -71,17 +71,17 @@ export const TyTabs = React.forwardRef<HTMLElement, TyTabsProps>(
71
71
  }
72
72
  }, [ref]);
73
73
 
74
- // Convert React props to web component attributes
75
74
  const webComponentProps: Record<string, any> = {
76
75
  ...hostProps(props),
77
76
  ref: elementRef,
78
77
  };
79
78
 
80
- // Add string attributes
81
79
  if (width) webComponentProps.width = width;
82
80
  if (height) webComponentProps.height = height;
83
81
  if (active) webComponentProps.active = active;
84
82
  if (placement) webComponentProps.placement = placement;
83
+ // Presence boolean — render the bare attribute only when true.
84
+ if (fixed) webComponentProps.fixed = '';
85
85
 
86
86
  return React.createElement(
87
87
  'ty-tabs',