tyrell-react 1.0.0-RC11 → 1.0.0-RC13
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/README.md +1 -0
- package/dist/components/TyButton.d.ts.map +1 -1
- package/dist/components/TyButton.js +2 -1
- package/dist/components/TyButton.js.map +1 -1
- package/dist/components/TyCalendar.d.ts +11 -0
- package/dist/components/TyCalendar.d.ts.map +1 -1
- package/dist/components/TyCalendar.js +21 -3
- package/dist/components/TyCalendar.js.map +1 -1
- package/dist/components/TyCalendarMonth.d.ts +9 -0
- package/dist/components/TyCalendarMonth.d.ts.map +1 -1
- package/dist/components/TyCalendarMonth.js +9 -2
- package/dist/components/TyCalendarMonth.js.map +1 -1
- package/dist/components/TyCalendarNavigation.d.ts +4 -0
- package/dist/components/TyCalendarNavigation.d.ts.map +1 -1
- package/dist/components/TyCalendarNavigation.js +7 -2
- package/dist/components/TyCalendarNavigation.js.map +1 -1
- package/dist/components/TyCheckbox.d.ts +6 -1
- package/dist/components/TyCheckbox.d.ts.map +1 -1
- package/dist/components/TyCheckbox.js +6 -2
- package/dist/components/TyCheckbox.js.map +1 -1
- package/dist/components/TyCopy.d.ts +8 -1
- package/dist/components/TyCopy.d.ts.map +1 -1
- package/dist/components/TyCopy.js +21 -2
- package/dist/components/TyCopy.js.map +1 -1
- package/dist/components/TyDatePicker.d.ts +15 -4
- package/dist/components/TyDatePicker.d.ts.map +1 -1
- package/dist/components/TyDatePicker.js +9 -2
- package/dist/components/TyDatePicker.js.map +1 -1
- package/dist/components/TyFileUpload.d.ts.map +1 -1
- package/dist/components/TyFileUpload.js +2 -1
- package/dist/components/TyFileUpload.js.map +1 -1
- package/dist/components/TyInput.d.ts +6 -2
- package/dist/components/TyInput.d.ts.map +1 -1
- package/dist/components/TyInput.js +2 -1
- package/dist/components/TyInput.js.map +1 -1
- package/dist/components/TyModal.d.ts +5 -0
- package/dist/components/TyModal.d.ts.map +1 -1
- package/dist/components/TyModal.js +5 -2
- package/dist/components/TyModal.js.map +1 -1
- package/dist/components/TyOption.d.ts +8 -0
- package/dist/components/TyOption.d.ts.map +1 -1
- package/dist/components/TyOption.js +5 -2
- package/dist/components/TyOption.js.map +1 -1
- package/dist/components/TyPopup.d.ts.map +1 -1
- package/dist/components/TyPopup.js +2 -1
- package/dist/components/TyPopup.js.map +1 -1
- package/dist/components/TyRadio.d.ts +4 -1
- package/dist/components/TyRadio.d.ts.map +1 -1
- package/dist/components/TyRadio.js +2 -1
- package/dist/components/TyRadio.js.map +1 -1
- package/dist/components/TyRadioGroup.d.ts +4 -1
- package/dist/components/TyRadioGroup.d.ts.map +1 -1
- package/dist/components/TyRadioGroup.js +2 -1
- package/dist/components/TyRadioGroup.js.map +1 -1
- package/dist/components/TyResizeObserver.d.ts.map +1 -1
- package/dist/components/TyResizeObserver.js +2 -1
- package/dist/components/TyResizeObserver.js.map +1 -1
- package/dist/components/TyScrollContainer.d.ts +26 -1
- package/dist/components/TyScrollContainer.d.ts.map +1 -1
- package/dist/components/TyScrollContainer.js +43 -25
- package/dist/components/TyScrollContainer.js.map +1 -1
- package/dist/components/TySelect.d.ts +114 -0
- package/dist/components/TySelect.d.ts.map +1 -0
- package/dist/components/TySelect.js +159 -0
- package/dist/components/TySelect.js.map +1 -0
- package/dist/components/TyStep.d.ts.map +1 -1
- package/dist/components/TyStep.js +2 -1
- package/dist/components/TyStep.js.map +1 -1
- package/dist/components/TySwitch.d.ts +4 -1
- package/dist/components/TySwitch.d.ts.map +1 -1
- package/dist/components/TySwitch.js +2 -1
- package/dist/components/TySwitch.js.map +1 -1
- package/dist/components/TyTab.d.ts.map +1 -1
- package/dist/components/TyTab.js +2 -1
- package/dist/components/TyTab.js.map +1 -1
- package/dist/components/TyTabs.d.ts.map +1 -1
- package/dist/components/TyTabs.js +2 -1
- package/dist/components/TyTabs.js.map +1 -1
- package/dist/components/TyTag.d.ts +4 -1
- package/dist/components/TyTag.d.ts.map +1 -1
- package/dist/components/TyTag.js +2 -1
- package/dist/components/TyTag.js.map +1 -1
- package/dist/components/TyTextarea.d.ts.map +1 -1
- package/dist/components/TyTextarea.js +2 -1
- package/dist/components/TyTextarea.js.map +1 -1
- package/dist/components/TyTooltip.d.ts +4 -1
- package/dist/components/TyTooltip.d.ts.map +1 -1
- package/dist/components/TyTooltip.js +2 -1
- package/dist/components/TyTooltip.js.map +1 -1
- package/dist/components/TyWizard.d.ts.map +1 -1
- package/dist/components/TyWizard.js +2 -1
- package/dist/components/TyWizard.js.map +1 -1
- package/dist/components/index.d.ts +6 -8
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -4
- package/dist/components/index.js.map +1 -1
- package/dist/utils/host-props.d.ts +11 -0
- package/dist/utils/host-props.d.ts.map +1 -0
- package/dist/utils/host-props.js +16 -0
- package/dist/utils/host-props.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/components/TyButton.tsx +2 -1
- package/src/components/TyCalendar.tsx +44 -3
- package/src/components/TyCalendarMonth.tsx +22 -3
- package/src/components/TyCalendarNavigation.tsx +13 -2
- package/src/components/TyCheckbox.tsx +14 -4
- package/src/components/TyCopy.tsx +31 -3
- package/src/components/TyDatePicker.tsx +31 -6
- package/src/components/TyFileUpload.tsx +2 -1
- package/src/components/TyInput.tsx +8 -3
- package/src/components/TyModal.tsx +10 -1
- package/src/components/TyOption.tsx +16 -2
- package/src/components/TyPopup.tsx +2 -1
- package/src/components/TyRadio.tsx +6 -2
- package/src/components/TyRadioGroup.tsx +6 -2
- package/src/components/TyResizeObserver.tsx +2 -1
- package/src/components/TyScrollContainer.tsx +76 -25
- package/src/components/TySelect.tsx +305 -0
- package/src/components/TyStep.tsx +2 -1
- package/src/components/TySwitch.tsx +6 -2
- package/src/components/TyTab.tsx +2 -1
- package/src/components/TyTabs.tsx +2 -1
- package/src/components/TyTag.tsx +6 -2
- package/src/components/TyTextarea.tsx +2 -1
- package/src/components/TyTooltip.tsx +6 -2
- package/src/components/TyWizard.tsx +2 -1
- package/src/components/index.ts +8 -13
- package/src/utils/host-props.ts +14 -0
- package/src/version.ts +1 -1
- package/dist/components/TyDropdown.d.ts +0 -62
- package/dist/components/TyDropdown.d.ts.map +0 -1
- package/dist/components/TyDropdown.js +0 -124
- package/dist/components/TyDropdown.js.map +0 -1
- package/dist/components/TyMultiselect.d.ts +0 -57
- package/dist/components/TyMultiselect.d.ts.map +0 -1
- package/dist/components/TyMultiselect.js +0 -111
- package/dist/components/TyMultiselect.js.map +0 -1
- package/src/components/EventConventionTest.tsx +0 -155
- package/src/components/TyDropdown.tsx +0 -240
- package/src/components/TyMultiselect.tsx +0 -208
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { hostProps } from '../utils/host-props';
|
|
3
|
+
import { needsPropertyBridge } from '../utils/react-version';
|
|
4
|
+
import { useBooleanProperty } from '../utils/use-boolean-prop';
|
|
5
|
+
|
|
6
|
+
type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
|
|
7
|
+
type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
|
|
8
|
+
|
|
9
|
+
// Type definitions for Ty Select component
|
|
10
|
+
export interface TySelectItem {
|
|
11
|
+
value: string;
|
|
12
|
+
label: string;
|
|
13
|
+
flavor: string | null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TySelectEventDetail {
|
|
17
|
+
/** Scalar for single select, array when `multiple` */
|
|
18
|
+
value: string | string[] | null;
|
|
19
|
+
/** Always the array form of the selection */
|
|
20
|
+
values: string[];
|
|
21
|
+
/** Rich info per selected value — enough to render chips out-of-band */
|
|
22
|
+
items: TySelectItem[];
|
|
23
|
+
/** Action that triggered the change */
|
|
24
|
+
action: 'add' | 'remove' | 'clear' | 'set' | 'create';
|
|
25
|
+
/** The specific value that changed */
|
|
26
|
+
item: string | null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface TySelectProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'style'> {
|
|
30
|
+
style?: import('./TyInput').TyInputCSSProperties;
|
|
31
|
+
|
|
32
|
+
/** Selected value(s) — string, comma-separated string, or array */
|
|
33
|
+
value?: string | string[];
|
|
34
|
+
|
|
35
|
+
/** Multi select (native <select multiple> semantics). Default: single. */
|
|
36
|
+
multiple?: boolean;
|
|
37
|
+
|
|
38
|
+
/** Compact content-hugging trigger (toolbars, filter bars) instead of the full-width field look */
|
|
39
|
+
compact?: boolean;
|
|
40
|
+
|
|
41
|
+
/** Placeholder shown while nothing is selected */
|
|
42
|
+
placeholder?: string;
|
|
43
|
+
|
|
44
|
+
/** Label text above the field */
|
|
45
|
+
label?: string;
|
|
46
|
+
|
|
47
|
+
/** Form field name — single submits one entry, multiple submits repeated entries */
|
|
48
|
+
name?: string;
|
|
49
|
+
|
|
50
|
+
/** Disable the select */
|
|
51
|
+
disabled?: boolean;
|
|
52
|
+
|
|
53
|
+
/** Read-only */
|
|
54
|
+
readonly?: boolean;
|
|
55
|
+
|
|
56
|
+
/** Mark the field as required */
|
|
57
|
+
required?: boolean;
|
|
58
|
+
|
|
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;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* External (remote) search mode — the component stops filtering and emits
|
|
67
|
+
* debounced `search` events; replace the option children in response.
|
|
68
|
+
*/
|
|
69
|
+
externalSearch?: boolean;
|
|
70
|
+
|
|
71
|
+
/** Debounce for the search event in ms (0-5000) */
|
|
72
|
+
debounce?: number;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Enter on unmatched search text mints a new <ty-option> (forces the
|
|
76
|
+
* search row on, same as externalSearch). Listen to onCreate to mutate
|
|
77
|
+
* the value before it's created, or preventDefault() to take over
|
|
78
|
+
* entirely (e.g. after a server round-trip).
|
|
79
|
+
*/
|
|
80
|
+
allowCreate?: boolean;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Opt-in normalizer for the value allowCreate mints — the display label
|
|
84
|
+
* is always kept verbatim. 'slug': lowercase, spaces → '_', strips
|
|
85
|
+
* everything else non-alphanumeric. Default: value === typed text.
|
|
86
|
+
*/
|
|
87
|
+
createTransform?: 'slug';
|
|
88
|
+
|
|
89
|
+
/** Loading state — shows a spinner in the options area (external search in flight) */
|
|
90
|
+
loading?: boolean;
|
|
91
|
+
|
|
92
|
+
/** Size variant */
|
|
93
|
+
/** Field size — fields come in exactly three; legacy xs/xl map to sm/lg */
|
|
94
|
+
size?: 'sm' | 'md' | 'lg';
|
|
95
|
+
|
|
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';
|
|
98
|
+
|
|
99
|
+
/** 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
|
+
clearable?: boolean;
|
|
101
|
+
|
|
102
|
+
/** Visual flavor for the field border — built-in semantic, +/- shade, or a custom flavor backed by --ty-*-X tokens */
|
|
103
|
+
flavor?: ShadedFlavor | (string & {});
|
|
104
|
+
|
|
105
|
+
/** Callback when selection changes */
|
|
106
|
+
onChange?: (event: CustomEvent<TySelectEventDetail>) => void;
|
|
107
|
+
|
|
108
|
+
/** Callback fired on each search input change (debounced). Use for external/server-side filtering. */
|
|
109
|
+
onSearch?: (event: CustomEvent<{ query: string; element: HTMLElement }>) => void;
|
|
110
|
+
onOpen?: (event: CustomEvent) => void;
|
|
111
|
+
onClose?: (event: CustomEvent) => void;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Fired before allowCreate mints a new option — cancelable. Mutate
|
|
115
|
+
* `event.detail.value` to change the id that gets created (e.g. slugify
|
|
116
|
+
* it yourself), or call `event.preventDefault()` to create it yourself.
|
|
117
|
+
*/
|
|
118
|
+
onCreate?: (event: CustomEvent<{ value: string; label: string }>) => void;
|
|
119
|
+
|
|
120
|
+
/** TyOption children (plus optional slot="trigger" / slot="start" / slot="end" elements) */
|
|
121
|
+
children?: React.ReactNode;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** The underlying custom element, typed with its imperative clear() method — useful with a ref, e.g. for slot="trigger" custom triggers that call it directly instead of relying on the built-in clear button. */
|
|
125
|
+
export interface TySelectElement extends HTMLElement {
|
|
126
|
+
clear(): void;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// React wrapper for ty-select web component
|
|
130
|
+
export const TySelect = React.forwardRef<TySelectElement, TySelectProps>(
|
|
131
|
+
({
|
|
132
|
+
value,
|
|
133
|
+
multiple,
|
|
134
|
+
compact,
|
|
135
|
+
placeholder,
|
|
136
|
+
label,
|
|
137
|
+
name,
|
|
138
|
+
disabled,
|
|
139
|
+
readonly,
|
|
140
|
+
required,
|
|
141
|
+
searchable,
|
|
142
|
+
externalSearch,
|
|
143
|
+
debounce,
|
|
144
|
+
allowCreate,
|
|
145
|
+
createTransform,
|
|
146
|
+
loading,
|
|
147
|
+
size,
|
|
148
|
+
align,
|
|
149
|
+
clearable,
|
|
150
|
+
flavor,
|
|
151
|
+
onChange,
|
|
152
|
+
onSearch,
|
|
153
|
+
onOpen,
|
|
154
|
+
onClose,
|
|
155
|
+
onCreate,
|
|
156
|
+
children,
|
|
157
|
+
...props
|
|
158
|
+
}, ref) => {
|
|
159
|
+
const elementRef = useRef<TySelectElement>(null);
|
|
160
|
+
|
|
161
|
+
// Handle ref forwarding
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (ref && elementRef.current) {
|
|
164
|
+
if (typeof ref === 'function') {
|
|
165
|
+
ref(elementRef.current);
|
|
166
|
+
} else {
|
|
167
|
+
ref.current = elementRef.current;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}, [ref]);
|
|
171
|
+
|
|
172
|
+
// Imperatively sync `value` so resets ('' or null) reliably clear the
|
|
173
|
+
// visible selection. React 18 workaround; React 19+ handles this natively.
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
if (!needsPropertyBridge) return;
|
|
176
|
+
const element = elementRef.current as any;
|
|
177
|
+
if (!element) return;
|
|
178
|
+
const next = Array.isArray(value) ? value.join(',') : (value ?? '');
|
|
179
|
+
if (element.value !== next) {
|
|
180
|
+
element.value = next;
|
|
181
|
+
}
|
|
182
|
+
}, [value]);
|
|
183
|
+
|
|
184
|
+
// Handle events
|
|
185
|
+
const handleChange = useCallback((event: Event) => {
|
|
186
|
+
if (onChange) onChange(event as CustomEvent<TySelectEventDetail>);
|
|
187
|
+
}, [onChange]);
|
|
188
|
+
|
|
189
|
+
const handleSearch = useCallback((event: Event) => {
|
|
190
|
+
if (onSearch) onSearch(event as CustomEvent<{ query: string; element: HTMLElement }>);
|
|
191
|
+
}, [onSearch]);
|
|
192
|
+
|
|
193
|
+
const handleOpen = useCallback((event: Event) => { if (onOpen) onOpen(event as CustomEvent); }, [onOpen]);
|
|
194
|
+
const handleClose = useCallback((event: Event) => { if (onClose) onClose(event as CustomEvent); }, [onClose]);
|
|
195
|
+
const handleCreate = useCallback((event: Event) => {
|
|
196
|
+
if (onCreate) onCreate(event as CustomEvent<{ value: string; label: string }>);
|
|
197
|
+
}, [onCreate]);
|
|
198
|
+
|
|
199
|
+
// Set up event listeners
|
|
200
|
+
useEffect(() => {
|
|
201
|
+
const element = elementRef.current;
|
|
202
|
+
if (!element) return;
|
|
203
|
+
|
|
204
|
+
if (onChange) element.addEventListener('change', handleChange);
|
|
205
|
+
if (onSearch) element.addEventListener('search', handleSearch);
|
|
206
|
+
if (onOpen) element.addEventListener('open', handleOpen);
|
|
207
|
+
if (onClose) element.addEventListener('close', handleClose);
|
|
208
|
+
if (onCreate) element.addEventListener('create', handleCreate);
|
|
209
|
+
|
|
210
|
+
return () => {
|
|
211
|
+
if (onChange) element.removeEventListener('change', handleChange);
|
|
212
|
+
if (onSearch) element.removeEventListener('search', handleSearch);
|
|
213
|
+
if (onOpen) element.removeEventListener('open', handleOpen);
|
|
214
|
+
if (onClose) element.removeEventListener('close', handleClose);
|
|
215
|
+
if (onCreate) element.removeEventListener('create', handleCreate);
|
|
216
|
+
};
|
|
217
|
+
}, [handleChange, handleSearch, handleOpen, handleClose, handleCreate, onChange, onSearch, onOpen, onClose, onCreate]);
|
|
218
|
+
|
|
219
|
+
// Imperative property sync for boolean props (see use-boolean-prop.ts).
|
|
220
|
+
const isMultiple = useBooleanProperty(elementRef, 'multiple', multiple);
|
|
221
|
+
const isCompact = useBooleanProperty(elementRef, 'compact', compact);
|
|
222
|
+
const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled);
|
|
223
|
+
const isReadonly = useBooleanProperty(elementRef, 'readonly', readonly);
|
|
224
|
+
const isRequired = useBooleanProperty(elementRef, 'required', required);
|
|
225
|
+
const isLoading = useBooleanProperty(elementRef, 'loading', loading);
|
|
226
|
+
const isExternalSearch = useBooleanProperty(elementRef, 'externalSearch', externalSearch);
|
|
227
|
+
const isAllowCreate = useBooleanProperty(elementRef, 'allowCreate', allowCreate);
|
|
228
|
+
const isClearable = useBooleanProperty(elementRef, 'clearable', clearable);
|
|
229
|
+
|
|
230
|
+
// Convert React props to web component attributes
|
|
231
|
+
const webComponentProps: Record<string, any> = {
|
|
232
|
+
...hostProps(props),
|
|
233
|
+
ref: elementRef,
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// Handle value conversion (array to comma-separated string)
|
|
237
|
+
if (value !== undefined) {
|
|
238
|
+
webComponentProps.value = Array.isArray(value) ? value.join(',') : value;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (isMultiple) webComponentProps.multiple = '';
|
|
242
|
+
if (isCompact) webComponentProps.compact = '';
|
|
243
|
+
if (isDisabled) webComponentProps.disabled = '';
|
|
244
|
+
if (isReadonly) webComponentProps.readonly = '';
|
|
245
|
+
if (isRequired) webComponentProps.required = '';
|
|
246
|
+
if (isLoading) webComponentProps.loading = '';
|
|
247
|
+
if (isExternalSearch) webComponentProps['external-search'] = '';
|
|
248
|
+
if (isAllowCreate) webComponentProps['allow-create'] = '';
|
|
249
|
+
|
|
250
|
+
if (placeholder) webComponentProps.placeholder = placeholder;
|
|
251
|
+
if (label) webComponentProps.label = label;
|
|
252
|
+
if (name) webComponentProps.name = name;
|
|
253
|
+
if (size) webComponentProps.size = size;
|
|
254
|
+
if (align) webComponentProps.align = align;
|
|
255
|
+
if (isClearable) webComponentProps.clearable = '';
|
|
256
|
+
if (flavor) webComponentProps.flavor = flavor;
|
|
257
|
+
if (debounce !== undefined) webComponentProps.debounce = debounce.toString();
|
|
258
|
+
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)
|
|
262
|
+
|
|
263
|
+
return React.createElement('ty-select', webComponentProps, children);
|
|
264
|
+
}
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
TySelect.displayName = 'TySelect';
|
|
268
|
+
|
|
269
|
+
// ============================================================================
|
|
270
|
+
// TySelectedOptions — out-of-band chip display for a TySelect
|
|
271
|
+
// (ty-selected-tags below is the same element under its original tag name,
|
|
272
|
+
// kept for backward compatibility.)
|
|
273
|
+
// ============================================================================
|
|
274
|
+
|
|
275
|
+
export interface TySelectedTagsProps extends React.HTMLAttributes<HTMLElement> {
|
|
276
|
+
/** id of the ty-select to display. Falls back to the previous element sibling. */
|
|
277
|
+
htmlFor?: string;
|
|
278
|
+
/** Optional <template> child as chip blueprint ({value}/{label}/{flavor}/{data-*} placeholders) */
|
|
279
|
+
children?: React.ReactNode;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const selectedChipsComponent = (tag: 'ty-selected-options' | 'ty-selected-tags') =>
|
|
283
|
+
React.forwardRef<HTMLElement, TySelectedTagsProps>(({ htmlFor, children, ...props }, ref) => {
|
|
284
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
285
|
+
|
|
286
|
+
useEffect(() => {
|
|
287
|
+
if (ref && elementRef.current) {
|
|
288
|
+
if (typeof ref === 'function') ref(elementRef.current);
|
|
289
|
+
else ref.current = elementRef.current;
|
|
290
|
+
}
|
|
291
|
+
}, [ref]);
|
|
292
|
+
|
|
293
|
+
const webComponentProps: Record<string, any> = { ...hostProps(props), ref: elementRef };
|
|
294
|
+
if (htmlFor) webComponentProps.for = htmlFor;
|
|
295
|
+
|
|
296
|
+
return React.createElement(tag, webComponentProps, children);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
/** React wrapper for the ty-selected-options web component. */
|
|
300
|
+
export const TySelectedOptions = selectedChipsComponent('ty-selected-options');
|
|
301
|
+
TySelectedOptions.displayName = 'TySelectedOptions';
|
|
302
|
+
|
|
303
|
+
/** @deprecated Use `TySelectedOptions` — kept for backward compatibility. */
|
|
304
|
+
export const TySelectedTags = selectedChipsComponent('ty-selected-tags');
|
|
305
|
+
TySelectedTags.displayName = 'TySelectedTags';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { hostProps } from '../utils/host-props';
|
|
2
3
|
|
|
3
4
|
// Type definitions for Ty Step component
|
|
4
5
|
export interface TyStepProps extends React.HTMLAttributes<HTMLElement> {
|
|
@@ -47,7 +48,7 @@ export const TyStep = React.forwardRef<HTMLElement, TyStepProps>(
|
|
|
47
48
|
|
|
48
49
|
// Convert React props to web component attributes
|
|
49
50
|
const webComponentProps: Record<string, any> = {
|
|
50
|
-
...props,
|
|
51
|
+
...hostProps(props),
|
|
51
52
|
ref: elementRef,
|
|
52
53
|
id,
|
|
53
54
|
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { hostProps } from '../utils/host-props';
|
|
2
3
|
import { useBooleanProperty } from '../utils/use-boolean-prop';
|
|
3
4
|
|
|
5
|
+
type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
|
|
6
|
+
type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
|
|
7
|
+
|
|
4
8
|
export interface TySwitchProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onInput'> {
|
|
5
9
|
/** Checked (on) state */
|
|
6
10
|
checked?: boolean;
|
|
@@ -21,7 +25,7 @@ export interface TySwitchProps extends Omit<React.HTMLAttributes<HTMLElement>, '
|
|
|
21
25
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
22
26
|
|
|
23
27
|
/** Semantic styling variant */
|
|
24
|
-
flavor?:
|
|
28
|
+
flavor?: ShadedFlavor | (string & {});
|
|
25
29
|
|
|
26
30
|
/**
|
|
27
31
|
* Fires when switch state changes (React convention)
|
|
@@ -94,7 +98,7 @@ export const TySwitch = React.forwardRef<HTMLElement, TySwitchProps>(
|
|
|
94
98
|
const isRequired = useBooleanProperty(elementRef, 'required', required);
|
|
95
99
|
|
|
96
100
|
const webComponentProps: Record<string, any> = {
|
|
97
|
-
...props,
|
|
101
|
+
...hostProps(props),
|
|
98
102
|
ref: elementRef,
|
|
99
103
|
};
|
|
100
104
|
|
package/src/components/TyTab.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { hostProps } from '../utils/host-props';
|
|
2
3
|
import { useBooleanProperty } from '../utils/use-boolean-prop';
|
|
3
4
|
|
|
4
5
|
// Type definitions for Ty Tab component
|
|
@@ -40,7 +41,7 @@ export const TyTab = React.forwardRef<HTMLElement, TyTabProps>(
|
|
|
40
41
|
|
|
41
42
|
// Convert React props to web component attributes
|
|
42
43
|
const webComponentProps: Record<string, any> = {
|
|
43
|
-
...props,
|
|
44
|
+
...hostProps(props),
|
|
44
45
|
ref: elementRef,
|
|
45
46
|
};
|
|
46
47
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { hostProps } from '../utils/host-props';
|
|
2
3
|
|
|
3
4
|
// Type definitions for Ty Tabs component
|
|
4
5
|
export interface TyTabsProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
@@ -72,7 +73,7 @@ export const TyTabs = React.forwardRef<HTMLElement, TyTabsProps>(
|
|
|
72
73
|
|
|
73
74
|
// Convert React props to web component attributes
|
|
74
75
|
const webComponentProps: Record<string, any> = {
|
|
75
|
-
...props,
|
|
76
|
+
...hostProps(props),
|
|
76
77
|
ref: elementRef,
|
|
77
78
|
};
|
|
78
79
|
|
package/src/components/TyTag.tsx
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { hostProps } from '../utils/host-props';
|
|
2
3
|
import { useBooleanProperty } from '../utils/use-boolean-prop';
|
|
3
4
|
|
|
5
|
+
type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
|
|
6
|
+
type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
|
|
7
|
+
|
|
4
8
|
// CSS custom properties that cascade into the shadow DOM for full color control
|
|
5
9
|
export interface TyTagCSSProperties extends React.CSSProperties {
|
|
6
10
|
'--tag-bg'?: string;
|
|
@@ -10,7 +14,7 @@ export interface TyTagCSSProperties extends React.CSSProperties {
|
|
|
10
14
|
|
|
11
15
|
// Type definitions for Ty Tag component
|
|
12
16
|
export interface TyTagProps extends Omit<React.HTMLAttributes<HTMLElement>, 'style' | 'onClick'> {
|
|
13
|
-
flavor?:
|
|
17
|
+
flavor?: ShadedFlavor | (string & {});
|
|
14
18
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
15
19
|
notPill?: boolean;
|
|
16
20
|
clickable?: boolean;
|
|
@@ -67,7 +71,7 @@ export const TyTag = React.forwardRef<HTMLElement, TyTagProps>(
|
|
|
67
71
|
return React.createElement(
|
|
68
72
|
'ty-tag',
|
|
69
73
|
{
|
|
70
|
-
...props,
|
|
74
|
+
...hostProps(props),
|
|
71
75
|
// click is dispatched as composed CustomEvent by the web component — React's
|
|
72
76
|
// synthetic onClick already catches it, so we just pass it through as onClick
|
|
73
77
|
...(onClick && { onClick }),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { hostProps } from '../utils/host-props';
|
|
2
3
|
import { needsPropertyBridge } from '../utils/react-version';
|
|
3
4
|
import { useBooleanProperty } from '../utils/use-boolean-prop';
|
|
4
5
|
|
|
@@ -167,7 +168,7 @@ export const TyTextarea = React.forwardRef<HTMLElement, TyTextareaProps>(
|
|
|
167
168
|
return React.createElement(
|
|
168
169
|
'ty-textarea',
|
|
169
170
|
{
|
|
170
|
-
...props,
|
|
171
|
+
...hostProps(props),
|
|
171
172
|
...(isDisabled && { disabled: "" }),
|
|
172
173
|
...(isRequired && { required: "" }),
|
|
173
174
|
...(minHeight && { 'min-height': minHeight }), // Convert camelCase to kebab-case
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { hostProps } from '../utils/host-props';
|
|
2
3
|
import { useBooleanProperty } from '../utils/use-boolean-prop';
|
|
3
4
|
|
|
5
|
+
type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
|
|
6
|
+
type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
|
|
7
|
+
|
|
4
8
|
// Type definitions for Ty Tooltip component
|
|
5
9
|
export interface TyTooltipProps extends React.HTMLAttributes<HTMLElement> {
|
|
6
10
|
/** Tooltip positioning relative to the parent element */
|
|
@@ -16,7 +20,7 @@ export interface TyTooltipProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
16
20
|
disabled?: boolean;
|
|
17
21
|
|
|
18
22
|
/** Semantic styling variant */
|
|
19
|
-
flavor?: 'dark' | 'light' | '
|
|
23
|
+
flavor?: 'dark' | 'light' | 'info' | ShadedFlavor | (string & {});
|
|
20
24
|
|
|
21
25
|
/** Tooltip content */
|
|
22
26
|
children?: React.ReactNode;
|
|
@@ -48,7 +52,7 @@ export const TyTooltip = React.forwardRef<HTMLElement, TyTooltipProps>(
|
|
|
48
52
|
|
|
49
53
|
// Convert React props to web component attributes
|
|
50
54
|
const webComponentProps: Record<string, any> = {
|
|
51
|
-
...props,
|
|
55
|
+
...hostProps(props),
|
|
52
56
|
ref: elementRef,
|
|
53
57
|
};
|
|
54
58
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { hostProps } from '../utils/host-props';
|
|
2
3
|
|
|
3
4
|
// Type definitions for Ty Wizard component
|
|
4
5
|
export interface TyWizardProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
@@ -77,7 +78,7 @@ export const TyWizard = React.forwardRef<HTMLElement, TyWizardProps>(
|
|
|
77
78
|
|
|
78
79
|
// Convert React props to web component attributes
|
|
79
80
|
const webComponentProps: Record<string, any> = {
|
|
80
|
-
...props,
|
|
81
|
+
...hostProps(props),
|
|
81
82
|
ref: elementRef,
|
|
82
83
|
};
|
|
83
84
|
|
package/src/components/index.ts
CHANGED
|
@@ -44,9 +44,6 @@ export type { TyInputProps, TyInputEventDetail, TyInputCSSProperties } from './T
|
|
|
44
44
|
export { TyTextarea } from './TyTextarea';
|
|
45
45
|
export type { TyTextareaProps, TyTextareaEventDetail } from './TyTextarea';
|
|
46
46
|
|
|
47
|
-
export { TyDropdown } from './TyDropdown';
|
|
48
|
-
export type { TyDropdownProps, TyDropdownEventDetail } from './TyDropdown';
|
|
49
|
-
|
|
50
47
|
export { TyOption } from './TyOption';
|
|
51
48
|
export type { TyOptionProps } from './TyOption';
|
|
52
49
|
|
|
@@ -55,12 +52,15 @@ export type { TyIconProps } from './TyIcon';
|
|
|
55
52
|
|
|
56
53
|
export { TyModal } from './TyModal';
|
|
57
54
|
export type { TyModalProps, TyModalEventDetail, TyModalRef } from './TyModal';
|
|
55
|
+
// Platform/ARIA name alias (the element is also registered as ty-dialog)
|
|
56
|
+
export { TyModal as TyDialog } from './TyModal';
|
|
57
|
+
export type { TyModalProps as TyDialogProps, TyModalEventDetail as TyDialogEventDetail, TyModalRef as TyDialogRef } from './TyModal';
|
|
58
58
|
|
|
59
59
|
export { TyTooltip } from './TyTooltip';
|
|
60
60
|
export type { TyTooltipProps } from './TyTooltip';
|
|
61
61
|
|
|
62
|
-
export {
|
|
63
|
-
export type {
|
|
62
|
+
export { TySelect, TySelectedOptions, TySelectedTags } from './TySelect';
|
|
63
|
+
export type { TySelectProps, TySelectEventDetail, TySelectItem, TySelectedTagsProps } from './TySelect';
|
|
64
64
|
|
|
65
65
|
export { TyCalendar } from './TyCalendar';
|
|
66
66
|
export type { TyCalendarProps, TyCalendarChangeEventDetail, TyCalendarNavigateEventDetail } from './TyCalendar';
|
|
@@ -85,6 +85,9 @@ export type { TyRadioGroupProps, TyRadioGroupEventDetail } from './TyRadioGroup'
|
|
|
85
85
|
|
|
86
86
|
export { TyCopy } from './TyCopy';
|
|
87
87
|
export type { TyCopyProps } from './TyCopy';
|
|
88
|
+
// Descriptive name alias (the element is also registered as ty-copy-field)
|
|
89
|
+
export { TyCopy as TyCopyField } from './TyCopy';
|
|
90
|
+
export type { TyCopyProps as TyCopyFieldProps } from './TyCopy';
|
|
88
91
|
|
|
89
92
|
export { TyFileUpload } from './TyFileUpload';
|
|
90
93
|
export type { TyFileUploadProps, TyFileUploadEventDetail } from './TyFileUpload';
|
|
@@ -122,12 +125,10 @@ export { TyButton as Button } from './TyButton';
|
|
|
122
125
|
export { TyTag as Tag } from './TyTag';
|
|
123
126
|
export { TyInput as Input } from './TyInput';
|
|
124
127
|
export { TyTextarea as Textarea } from './TyTextarea';
|
|
125
|
-
export { TyDropdown as Dropdown } from './TyDropdown';
|
|
126
128
|
export { TyOption as Option } from './TyOption';
|
|
127
129
|
export { TyIcon as Icon } from './TyIcon';
|
|
128
130
|
export { TyModal as Modal } from './TyModal';
|
|
129
131
|
export { TyTooltip as Tooltip } from './TyTooltip';
|
|
130
|
-
export { TyMultiselect as Multiselect } from './TyMultiselect';
|
|
131
132
|
export { TyCalendar as Calendar } from './TyCalendar';
|
|
132
133
|
export { TyDatePicker as DatePicker } from './TyDatePicker';
|
|
133
134
|
export { TyPopup as Popup } from './TyPopup';
|
|
@@ -162,9 +163,6 @@ export type { TyInputProps as InputProps, TyInputEventDetail as InputEventDetail
|
|
|
162
163
|
// Textarea types
|
|
163
164
|
export type { TyTextareaProps as TextareaProps, TyTextareaEventDetail as TextareaEventDetail } from './TyTextarea';
|
|
164
165
|
|
|
165
|
-
// Dropdown types
|
|
166
|
-
export type { TyDropdownProps as DropdownProps, TyDropdownEventDetail as DropdownEventDetail, OptionData } from './TyDropdown';
|
|
167
|
-
|
|
168
166
|
// Option types
|
|
169
167
|
export type { TyOptionProps as OptionProps } from './TyOption';
|
|
170
168
|
|
|
@@ -177,9 +175,6 @@ export type { TyModalProps as ModalProps, TyModalEventDetail as ModalEventDetail
|
|
|
177
175
|
// Tooltip types
|
|
178
176
|
export type { TyTooltipProps as TooltipProps } from './TyTooltip';
|
|
179
177
|
|
|
180
|
-
// Multiselect types
|
|
181
|
-
export type { TyMultiselectProps as MultiselectProps, TyMultiselectEventDetail as MultiselectEventDetail } from './TyMultiselect';
|
|
182
|
-
|
|
183
178
|
// Calendar types
|
|
184
179
|
export type { TyCalendarProps as CalendarProps, TyCalendarChangeEventDetail as CalendarChangeEventDetail, TyCalendarNavigateEventDetail as CalendarNavigateEventDetail } from './TyCalendar';
|
|
185
180
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize pass-through props for a custom-element host.
|
|
3
|
+
*
|
|
4
|
+
* React 18 does not special-case `className` on custom elements — it
|
|
5
|
+
* lowercases the prop into a literal `classname=""` attribute, which no CSS
|
|
6
|
+
* ever matches. Renaming it to `class` makes React pass it through verbatim,
|
|
7
|
+
* so host-level utility classes (layout, positioning) actually apply.
|
|
8
|
+
* React 19 handles `className` natively; this stays harmless there.
|
|
9
|
+
*/
|
|
10
|
+
export function hostProps<T extends Record<string, any>>(props: T): Record<string, any> {
|
|
11
|
+
const { className, ...rest } = props;
|
|
12
|
+
if (className != null) (rest as Record<string, any>).class = className;
|
|
13
|
+
return rest;
|
|
14
|
+
}
|
package/src/version.ts
CHANGED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export interface OptionData {
|
|
3
|
-
value: string;
|
|
4
|
-
text: string;
|
|
5
|
-
disabled?: boolean;
|
|
6
|
-
}
|
|
7
|
-
export interface TyDropdownEventDetail {
|
|
8
|
-
option: HTMLElement;
|
|
9
|
-
}
|
|
10
|
-
export interface TyDropdownProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'style'> {
|
|
11
|
-
style?: import('./TyInput').TyInputCSSProperties;
|
|
12
|
-
/** Semantic styling variant */
|
|
13
|
-
flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
|
|
14
|
-
/** Dropdown size */
|
|
15
|
-
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
16
|
-
/** Selected value */
|
|
17
|
-
value?: string;
|
|
18
|
-
/** Placeholder text */
|
|
19
|
-
placeholder?: string;
|
|
20
|
-
/** Dropdown label */
|
|
21
|
-
label?: string;
|
|
22
|
-
/** Disable the dropdown */
|
|
23
|
-
disabled?: boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Loading state — replaces the open popup options list with a centered
|
|
26
|
-
* spinner. Search input stays usable. Pair with `externalSearch` while
|
|
27
|
-
* fetching results from a parent-owned data source.
|
|
28
|
-
*/
|
|
29
|
-
loading?: boolean;
|
|
30
|
-
/** Make dropdown readonly */
|
|
31
|
-
readonly?: boolean;
|
|
32
|
-
/** Required field */
|
|
33
|
-
required?: boolean;
|
|
34
|
-
/** Show clear button */
|
|
35
|
-
clearable?: boolean;
|
|
36
|
-
/** Disable clear button (alias for clearable={false}) */
|
|
37
|
-
notClearable?: boolean;
|
|
38
|
-
/** Debounce in milliseconds (0-5000) */
|
|
39
|
-
debounce?: number;
|
|
40
|
-
/**
|
|
41
|
-
* Switch to external (remote) search mode. Default is `false` — the dropdown
|
|
42
|
-
* filters its options locally. When `true`, the dropdown stops filtering and
|
|
43
|
-
* dispatches `search` events on each keystroke; the parent owns filtering
|
|
44
|
-
* and updates the children.
|
|
45
|
-
*/
|
|
46
|
-
externalSearch?: boolean;
|
|
47
|
-
/** @deprecated Use `externalSearch` instead. */
|
|
48
|
-
notSearchable?: boolean;
|
|
49
|
-
/** @deprecated Use `externalSearch` instead. Pass `searchable={false}` was equivalent to `externalSearch={true}`. */
|
|
50
|
-
searchable?: boolean;
|
|
51
|
-
/** Form field name for form submission */
|
|
52
|
-
name?: string;
|
|
53
|
-
options?: OptionData[];
|
|
54
|
-
onChange?: (event: CustomEvent<TyDropdownEventDetail>) => void;
|
|
55
|
-
onSearch?: (event: CustomEvent<{
|
|
56
|
-
query: string;
|
|
57
|
-
element: HTMLElement;
|
|
58
|
-
}>) => void;
|
|
59
|
-
children?: React.ReactNode;
|
|
60
|
-
}
|
|
61
|
-
export declare const TyDropdown: React.ForwardRefExoticComponent<TyDropdownProps & React.RefAttributes<HTMLElement>>;
|
|
62
|
-
//# sourceMappingURL=TyDropdown.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TyDropdown.d.ts","sourceRoot":"","sources":["../../src/components/TyDropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAK9D,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAGD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,WAAW,CAAC;CACrB;AAGD,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IACpG,KAAK,CAAC,EAAE,OAAO,WAAW,EAAE,oBAAoB,CAAC;IACjD,+BAA+B;IAC/B,MAAM,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IAEhF,oBAAoB;IACpB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAExC,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,uBAAuB;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,wBAAwB;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,yDAAyD;IACzD,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,gDAAgD;IAChD,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,qHAAqH;IACrH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IAGvB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,qBAAqB,CAAC,KAAK,IAAI,CAAC;IAC/D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,KAAK,IAAI,CAAC;IAGjF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAGD,eAAO,MAAM,UAAU,qFAqJtB,CAAC"}
|