@dloizides/ui-forms 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/README.md +42 -0
- package/dist/index.d.mts +275 -2
- package/dist/index.d.ts +275 -2
- package/dist/index.js +408 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +401 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.8.0
|
|
4
|
+
|
|
5
|
+
**Campaign F2 — the dense CONTROLS arrive.** `@dloizides/ui-tables` shipped a complete, themed,
|
|
6
|
+
a11y-wired set of form controls inside its `Filters` bar and exported NONE of them: its
|
|
7
|
+
`src/index.ts` exposed only `Filters`, `useFilterDraft`, `suggestOptions`, `isUnmatched` and
|
|
8
|
+
types. Six portals could SEE those controls working and none could import them, so the fleet
|
|
9
|
+
reimplemented them — **6 independent select implementations, 5 date fields, 2 typeaheads**. Same
|
|
10
|
+
shape as `MultiTenancy.EntityFrameworkCore` shipping no EF Core. This release makes them public.
|
|
11
|
+
|
|
12
|
+
Nothing here moves a pixel for an existing consumer: the metrics are the promoted originals,
|
|
13
|
+
unchanged. `CONTAINER_MARGIN_BOTTOM` and `ChipSelector`'s compensating `marginBottom:
|
|
14
|
+
-CHIP_GUTTER` remain deliberately untouched.
|
|
15
|
+
|
|
16
|
+
- **Add `SelectControl`** — single-select enum/status dropdown. Bordered trigger + chevron opening
|
|
17
|
+
the shared `AnchoredMenu`.
|
|
18
|
+
- **Add `TypeaheadControl`** — search-as-you-type combobox (aml-v2's CountryPicker, generalized).
|
|
19
|
+
Free typing is preserved (the value is raw text the caller normalises at query time); picking a
|
|
20
|
+
suggestion fills the canonical LABEL, not the value.
|
|
21
|
+
- **Add `DateRangeControl`** — inclusive from/to pair. Editing one side patches ONLY that side.
|
|
22
|
+
- **Add `AnchoredMenu`** — the floating option list both of the above compose. Kept in-tree with
|
|
23
|
+
NO `ui-layout` dependency; that was a considered choice in `ui-tables` and it still holds, since
|
|
24
|
+
depending on the higher-level `ModalDropdown` would invert the graph for every consumer.
|
|
25
|
+
- **Add `controlStyles`** — the tuned metrics, promoted verbatim. `ui-tables`' `Filters/styles.ts`
|
|
26
|
+
said the quiet part out loud in its own header: it "reconcile[d] the per-field styles that were
|
|
27
|
+
copy-pasted across aml-v2's filter files into one shared source" — and then locked the
|
|
28
|
+
reconciliation inside one bar where no other surface could reach it.
|
|
29
|
+
- **Add `suggestOptions` / `isUnmatched`** — the ranked substring matcher behind the typeahead.
|
|
30
|
+
- **Add `ControlOption` / `DateRangeValue`** types. `ui-tables` now ALIASES its long-standing
|
|
31
|
+
public `FilterOption` / `DateRangeValue` onto these, so there is one definition rather than two
|
|
32
|
+
structurally-compatible twins free to drift.
|
|
33
|
+
|
|
34
|
+
### The controls are LABEL-FREE, on purpose
|
|
35
|
+
|
|
36
|
+
They render the control only. Compose them inside `Field` — with `labelVariant="control"` on a
|
|
37
|
+
dense surface — to get the label, hint and error slots. That is what retires `ui-tables`' private
|
|
38
|
+
`FieldShell` fork (see `@dloizides/ui-tables` 1.14.0) and leaves ONE label implementation for
|
|
39
|
+
every control instead of one per control.
|
|
40
|
+
|
|
41
|
+
### i18n: this package still never calls `t`
|
|
42
|
+
|
|
43
|
+
Every string — `accessibilityLabel`, `placeholder`, `optionHint`, `error`, `fromLabel`/`toLabel`
|
|
44
|
+
— is a PRE-LOCALIZED prop. This is load-bearing, not stylistic: aml-v2 localizes through
|
|
45
|
+
`@dloizides/i18n` with positional `{0}` while the other six portals use i18next `{{p1}}`, so a
|
|
46
|
+
component that localized internally could not serve both. `SelectControl`'s `accessibilityLabel`
|
|
47
|
+
is therefore composed BY THE CALLER — it must carry the selection ("Status: Active", not
|
|
48
|
+
"Status"), and building that string needs a `t` call this package must not make.
|
|
49
|
+
|
|
50
|
+
### Fixed — a WCAG defect carried in by the promoted code
|
|
51
|
+
|
|
52
|
+
`AnchoredMenu` marked the current option with `accessibilityState={{ selected }}` alone.
|
|
53
|
+
**react-native-web does not read `accessibilityState` at all** (verified against
|
|
54
|
+
`react-native-web@0.21`'s `createDOMProps`, which enumerates `aria-selected` /
|
|
55
|
+
`accessibilitySelected` and never `accessibilityState`), so on web the selected option was
|
|
56
|
+
distinguished by colour and font-weight ONLY — no screen reader could tell which option was
|
|
57
|
+
current (WCAG 1.4.1, use of colour). `aria-selected` is now passed alongside, so each platform
|
|
58
|
+
gets the channel it honours. The trigger already paired `aria-expanded` with `accessibilityState`;
|
|
59
|
+
the option row was simply missed when that was done. A test asserts it, and that test FAILED
|
|
60
|
+
before the fix.
|
|
61
|
+
|
|
3
62
|
## 1.7.0
|
|
4
63
|
|
|
5
64
|
Additive wave implementing the shared cross-stack forms contract now written down at
|
package/README.md
CHANGED
|
@@ -98,6 +98,48 @@ with no label no label row is rendered, so it drops into a toolbar or filter bar
|
|
|
98
98
|
| `containerStyle` | `ViewStyle` | merged over the container |
|
|
99
99
|
| `testID` | `string` | on the container |
|
|
100
100
|
|
|
101
|
+
## Dense controls — `SelectControl` / `TypeaheadControl` / `DateRangeControl`
|
|
102
|
+
|
|
103
|
+
Promoted in 1.8.0 out of `@dloizides/ui-tables`' private filter bar, where they worked correctly
|
|
104
|
+
for six portals and were exported to none — which is why the fleet grew 6 selects, 5 date fields
|
|
105
|
+
and 2 typeaheads.
|
|
106
|
+
|
|
107
|
+
They are **label-free by design**. Compose them inside `Field` so there is ONE label
|
|
108
|
+
implementation for every control rather than one per control:
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
<Field label="Status" labelVariant="control" containerStyle={{ marginBottom: 0 }}>
|
|
112
|
+
<SelectControl
|
|
113
|
+
accessibilityLabel={t('filters.statusName', 'Status', selectedLabel)}
|
|
114
|
+
options={options}
|
|
115
|
+
testID="filters-status"
|
|
116
|
+
value={value}
|
|
117
|
+
onChange={setValue}
|
|
118
|
+
/>
|
|
119
|
+
</Field>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`labelVariant="control"` is the 11/700/uppercase voice from
|
|
123
|
+
[`FORMS.md`](../../../PROOViD/AMLService/AMLService/wwwroot/shared/FORMS.md) — the voice for
|
|
124
|
+
labels that are SCANNED (filter bars, toolbars) rather than READ.
|
|
125
|
+
|
|
126
|
+
### Every string is pre-localized
|
|
127
|
+
|
|
128
|
+
This package never calls `t`. In particular `SelectControl`'s `accessibilityLabel` must be
|
|
129
|
+
composed by YOU and must carry the **selection** — "Status: Active", not "Status". The accessible
|
|
130
|
+
name REPLACES the trigger's visible text for a screen reader, so naming it with the field alone
|
|
131
|
+
silently hides what is selected.
|
|
132
|
+
|
|
133
|
+
| Control | Key props | testIDs |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| `SelectControl` | `options`, `value`, `onChange`, `placeholder`, `accessibilityLabel`, `optionHint` | `<testID>-trigger`, `-menu`, `-option-<value>` |
|
|
136
|
+
| `TypeaheadControl` | `options`, `value`, `onChange`, `onSubmit`, `error`, `minChars`, `maxSuggestions` | `<testID>-input`, `-menu`, `-error` |
|
|
137
|
+
| `DateRangeControl` | `value` (`{from,to}`), `onChange`, `onSubmit`, `fromLabel`, `toLabel` | `<testID>-range`, `-from`, `-to` |
|
|
138
|
+
| `AnchoredMenu` | the floating list the first two compose | `<testID>-menu` |
|
|
139
|
+
|
|
140
|
+
Also exported: `controlStyles` (the tuned metrics), `suggestOptions` / `isUnmatched` (the
|
|
141
|
+
typeahead's ranker), and the `ControlOption` / `DateRangeValue` types.
|
|
142
|
+
|
|
101
143
|
## testIDs
|
|
102
144
|
|
|
103
145
|
`form-field-input`, `chip-selector-chip-<value>`, `form-switch` (overridable on FormSwitch).
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { StyleProp, TextStyle, ViewStyle, TextInputProps, TextInput } from 'react-native';
|
|
2
|
+
import { StyleProp, TextStyle, ViewStyle, TextInputProps, TextInput, View } from 'react-native';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* The TWO legitimate label voices, per the shared forms contract
|
|
@@ -351,4 +351,277 @@ interface FormCheckboxProps {
|
|
|
351
351
|
}
|
|
352
352
|
declare const FormCheckbox: ({ label, value, onValueChange, onChange, hint, description, disabled, containerStyle, testID, accessibilityLabel, accessibilityHint, }: FormCheckboxProps) => React.ReactElement;
|
|
353
353
|
|
|
354
|
-
|
|
354
|
+
/**
|
|
355
|
+
* Shared value types for the dense CONTROLS (select / typeahead / date-range) promoted out of
|
|
356
|
+
* `@dloizides/ui-tables`' private filter bar.
|
|
357
|
+
*
|
|
358
|
+
* They live here, not in `ui-tables`, because a control's option list and a date range are form
|
|
359
|
+
* concepts — a filter bar is only one surface that happens to compose them. `ui-tables` aliases
|
|
360
|
+
* its long-standing public names (`FilterOption`, `DateRangeValue`) onto these, so there is ONE
|
|
361
|
+
* definition and the two can never drift into structurally-compatible-but-separate twins.
|
|
362
|
+
*/
|
|
363
|
+
/** A single choice in a select / typeahead. `label` is PRE-LOCALIZED by the caller. */
|
|
364
|
+
interface ControlOption {
|
|
365
|
+
readonly label: string;
|
|
366
|
+
readonly value: string;
|
|
367
|
+
}
|
|
368
|
+
/** The inclusive from/to value of a date-range control (each an ISO `YYYY-MM-DD` string, or ''). */
|
|
369
|
+
interface DateRangeValue {
|
|
370
|
+
readonly from: string;
|
|
371
|
+
readonly to: string;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* `SelectControl` — a single-select enum/status dropdown. A bordered trigger shows the selected
|
|
376
|
+
* option's label (or the placeholder when unset) plus a chevron; pressing it opens the shared
|
|
377
|
+
* {@link AnchoredMenu}. Selecting fires `onChange` and closes.
|
|
378
|
+
*
|
|
379
|
+
* Promoted out of `@dloizides/ui-tables`' private `Filters/fields/SelectField`, where six portals
|
|
380
|
+
* could see it working and none could import it — which is why the fleet grew SIX independent
|
|
381
|
+
* select implementations.
|
|
382
|
+
*
|
|
383
|
+
* The control is LABEL-FREE by design: wrap it in a `Field` (with `labelVariant="control"` on a
|
|
384
|
+
* dense surface) to get the label, hint and error slots. That keeps one label implementation for
|
|
385
|
+
* every control instead of one per control.
|
|
386
|
+
*
|
|
387
|
+
* i18n: this package never calls `t`. `accessibilityLabel`, `placeholder`, `accessibilityHint`
|
|
388
|
+
* and `optionHint` are PRE-LOCALIZED strings supplied by the caller — the only shape that can
|
|
389
|
+
* serve both aml-v2's positional `{0}` `@dloizides/i18n` and the other six portals' i18next
|
|
390
|
+
* `{{p1}}` from one component.
|
|
391
|
+
*/
|
|
392
|
+
|
|
393
|
+
interface SelectControlProps {
|
|
394
|
+
options: readonly ControlOption[];
|
|
395
|
+
/** The selected option's `value`. `''` (or any unmatched value) renders the placeholder. */
|
|
396
|
+
value: string;
|
|
397
|
+
onChange: (value: string) => void;
|
|
398
|
+
/** PRE-LOCALIZED text shown when the value matches no option. */
|
|
399
|
+
placeholder?: string;
|
|
400
|
+
/**
|
|
401
|
+
* PRE-LOCALIZED accessible NAME of the trigger. It REPLACES the trigger's visible text for a
|
|
402
|
+
* screen reader, so it must carry the SELECTION too — "Status: Active", not just "Status",
|
|
403
|
+
* which announces the control but silently hides its value.
|
|
404
|
+
*/
|
|
405
|
+
accessibilityLabel: string;
|
|
406
|
+
accessibilityHint?: string;
|
|
407
|
+
/** PRE-LOCALIZED accessibility hint applied to every option in the menu. */
|
|
408
|
+
optionHint?: string;
|
|
409
|
+
/** Merged LAST onto the anchor wrapper — the consumer always wins over the shared style. */
|
|
410
|
+
style?: StyleProp<ViewStyle>;
|
|
411
|
+
/** Trigger is `${testID}-trigger`, menu `${testID}-menu`, options `${testID}-option-${value}`. */
|
|
412
|
+
testID: string;
|
|
413
|
+
}
|
|
414
|
+
declare function SelectControl({ options, value, onChange, placeholder, accessibilityLabel, accessibilityHint, optionHint, style, testID, }: SelectControlProps): React.ReactElement;
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* `TypeaheadControl` — a search-as-you-type combobox (aml-v2's CountryPicker, generalized). A
|
|
418
|
+
* text input plus a floating {@link AnchoredMenu} of ranked suggestions ({@link suggestOptions});
|
|
419
|
+
* picking one fills the canonical label.
|
|
420
|
+
*
|
|
421
|
+
* Free typing is PRESERVED: the value is the raw text, so a caller can accept "CY", "cyprus" or
|
|
422
|
+
* "Cyprus (CY)" and normalise it themselves at query time, exactly as aml does. An optional
|
|
423
|
+
* PRE-LOCALIZED `error` shows a persistent banner and tints the border.
|
|
424
|
+
*
|
|
425
|
+
* Promoted out of `@dloizides/ui-tables`' private `Filters/fields/TypeaheadField`.
|
|
426
|
+
*
|
|
427
|
+
* Label-free by design — wrap in a `Field` for the label/hint slots.
|
|
428
|
+
*/
|
|
429
|
+
|
|
430
|
+
/** Default min characters before suggestions surface. */
|
|
431
|
+
declare const DEFAULT_TYPEAHEAD_MIN_CHARS = 1;
|
|
432
|
+
/** Default cap on rendered suggestions. */
|
|
433
|
+
declare const DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS = 8;
|
|
434
|
+
interface TypeaheadControlProps {
|
|
435
|
+
options: readonly ControlOption[];
|
|
436
|
+
/** The raw text in the box — NOT necessarily an option value. */
|
|
437
|
+
value: string;
|
|
438
|
+
onChange: (value: string) => void;
|
|
439
|
+
/** Called on Enter/submit (after the menu closes). Omit if the surface has nothing to commit. */
|
|
440
|
+
onSubmit?: () => void;
|
|
441
|
+
placeholder?: string;
|
|
442
|
+
/** PRE-LOCALIZED accessible name of the input. */
|
|
443
|
+
accessibilityLabel: string;
|
|
444
|
+
accessibilityHint?: string;
|
|
445
|
+
/** PRE-LOCALIZED accessibility hint applied to every suggestion. */
|
|
446
|
+
optionHint?: string;
|
|
447
|
+
/** PRE-LOCALIZED inline error (e.g. "Unrecognised country"). Shows a persistent banner. */
|
|
448
|
+
error?: string;
|
|
449
|
+
/** Minimum characters before suggestions surface. Default 1. */
|
|
450
|
+
minChars?: number;
|
|
451
|
+
/** Cap on rendered suggestions. Default 8. */
|
|
452
|
+
maxSuggestions?: number;
|
|
453
|
+
/** Merged LAST onto the anchor wrapper. */
|
|
454
|
+
style?: StyleProp<ViewStyle>;
|
|
455
|
+
/** Input is `${testID}-input`, menu `${testID}-menu`, error `${testID}-error`. */
|
|
456
|
+
testID: string;
|
|
457
|
+
}
|
|
458
|
+
declare function TypeaheadControl({ options, value, onChange, onSubmit, placeholder, accessibilityLabel, accessibilityHint, optionHint, error, minChars, maxSuggestions, style, testID, }: TypeaheadControlProps): React.ReactElement;
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* `DateRangeControl` — an inclusive from/to pair (aml cases `from`/`to`, kefi audit `from`/`to`).
|
|
462
|
+
* Each side is a `YYYY-MM-DD` text input; on web the browser's native date UI is offered via
|
|
463
|
+
* `type="date"` (a react-native-web `TextInput` passes unknown props to the DOM input). Editing
|
|
464
|
+
* either side patches ONLY that side, so the other survives the edit.
|
|
465
|
+
*
|
|
466
|
+
* Promoted out of `@dloizides/ui-tables`' private `Filters/fields/DateRangeField`, which is why
|
|
467
|
+
* the fleet grew FIVE independent date fields.
|
|
468
|
+
*
|
|
469
|
+
* Label-free by design — the From/To sub-labels name the two HALVES; wrap in a `Field` for the
|
|
470
|
+
* range's own label.
|
|
471
|
+
*/
|
|
472
|
+
|
|
473
|
+
interface DateRangeControlProps {
|
|
474
|
+
value: DateRangeValue;
|
|
475
|
+
onChange: (value: DateRangeValue) => void;
|
|
476
|
+
/** Called on Enter/submit in either side. */
|
|
477
|
+
onSubmit?: () => void;
|
|
478
|
+
/** PRE-LOCALIZED sub-label for the FROM input (e.g. "From"). Also its accessible name. */
|
|
479
|
+
fromLabel: string;
|
|
480
|
+
/** PRE-LOCALIZED sub-label for the TO input (e.g. "To"). Also its accessible name. */
|
|
481
|
+
toLabel: string;
|
|
482
|
+
fromPlaceholder?: string;
|
|
483
|
+
toPlaceholder?: string;
|
|
484
|
+
/** PRE-LOCALIZED hint applied to BOTH inputs. */
|
|
485
|
+
accessibilityHint?: string;
|
|
486
|
+
/** Merged LAST onto the row wrapper. */
|
|
487
|
+
style?: StyleProp<ViewStyle>;
|
|
488
|
+
/** Row is `${testID}-range`, inputs `${testID}-from` / `${testID}-to`. */
|
|
489
|
+
testID: string;
|
|
490
|
+
}
|
|
491
|
+
declare function DateRangeControl({ value, onChange, onSubmit, fromLabel, toLabel, fromPlaceholder, toPlaceholder, accessibilityHint, style, testID, }: DateRangeControlProps): React.ReactElement;
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* `AnchoredMenu` — the floating option list shared by `SelectControl` and `TypeaheadControl`.
|
|
495
|
+
*
|
|
496
|
+
* Renders an in-tree, absolutely-positioned popover under its anchor (the pattern aml-v2's
|
|
497
|
+
* CountryPicker proved: `position:absolute; top:100%; zIndex; elevation`), so it floats over
|
|
498
|
+
* sibling fields without a portal. On web it dismisses on outside-click / Escape; on native the
|
|
499
|
+
* caller closes it on blur/select. Purely presentational + theme-flat, so it stays reusable.
|
|
500
|
+
*
|
|
501
|
+
* Promoted verbatim out of `@dloizides/ui-tables`' private `Filters/components/AnchoredMenu`.
|
|
502
|
+
*
|
|
503
|
+
* Deliberately in-tree (no `ui-layout` dependency). That was a considered choice in `ui-tables`
|
|
504
|
+
* and it still holds here: `ui-forms` is a low-level primitive and must not take a runtime
|
|
505
|
+
* dependency on the higher-level `ui-layout` `ModalDropdown` — that would invert the graph for
|
|
506
|
+
* every consumer. Apps needing the responsive modal/bottom-sheet variant inject it instead.
|
|
507
|
+
*/
|
|
508
|
+
|
|
509
|
+
/** The four theme colours the menu paints with — passed in, so the menu stays theme-flat. */
|
|
510
|
+
interface AnchoredMenuColors {
|
|
511
|
+
text: string;
|
|
512
|
+
border: string;
|
|
513
|
+
surface: string;
|
|
514
|
+
brand: string;
|
|
515
|
+
}
|
|
516
|
+
interface AnchoredMenuProps {
|
|
517
|
+
options: readonly ControlOption[];
|
|
518
|
+
/** The currently-selected value, highlighted in the list ('' = none). */
|
|
519
|
+
selectedValue: string;
|
|
520
|
+
onSelect: (value: string) => void;
|
|
521
|
+
onDismiss: () => void;
|
|
522
|
+
colors: AnchoredMenuColors;
|
|
523
|
+
/** PRE-LOCALIZED accessibility hint applied to every option. */
|
|
524
|
+
optionHint: string;
|
|
525
|
+
/** Base testID: the menu is `${testID}-menu`, each option `${testID}-option-${value}`. */
|
|
526
|
+
testID: string;
|
|
527
|
+
/** Node whose clicks count as "inside" (the anchor) so its own press doesn't self-dismiss. */
|
|
528
|
+
anchorRef: React.RefObject<View | null>;
|
|
529
|
+
}
|
|
530
|
+
declare function AnchoredMenu({ options, selectedValue, onSelect, onDismiss, colors, optionHint, testID, anchorRef, }: AnchoredMenuProps): React.ReactElement;
|
|
531
|
+
|
|
532
|
+
declare const controlStyles: {
|
|
533
|
+
/** The shared bordered box every dense text control renders in. */
|
|
534
|
+
input: {
|
|
535
|
+
borderWidth: number;
|
|
536
|
+
borderRadius: number;
|
|
537
|
+
paddingHorizontal: number;
|
|
538
|
+
paddingVertical: number;
|
|
539
|
+
fontSize: number;
|
|
540
|
+
};
|
|
541
|
+
/** The select trigger: a bordered field box matching the text inputs + a chevron. */
|
|
542
|
+
selectTrigger: {
|
|
543
|
+
flexDirection: "row";
|
|
544
|
+
alignItems: "center";
|
|
545
|
+
justifyContent: "space-between";
|
|
546
|
+
gap: number;
|
|
547
|
+
borderWidth: number;
|
|
548
|
+
borderRadius: number;
|
|
549
|
+
paddingHorizontal: number;
|
|
550
|
+
paddingVertical: number;
|
|
551
|
+
};
|
|
552
|
+
selectTriggerText: {
|
|
553
|
+
fontSize: number;
|
|
554
|
+
flexShrink: number;
|
|
555
|
+
};
|
|
556
|
+
chevron: {
|
|
557
|
+
fontSize: number;
|
|
558
|
+
};
|
|
559
|
+
dateRow: {
|
|
560
|
+
flexDirection: "row";
|
|
561
|
+
gap: number;
|
|
562
|
+
};
|
|
563
|
+
dateCol: {
|
|
564
|
+
gap: number;
|
|
565
|
+
flex: number;
|
|
566
|
+
};
|
|
567
|
+
/**
|
|
568
|
+
* The micro-caption above a sub-control (a date range's From/To) and beside a switch. Note it
|
|
569
|
+
* is deliberately NOT the `control` label voice: it carries no `700`/uppercase, because it
|
|
570
|
+
* names a HALF of a control that already has a `control`-voice label above it. Uppercasing it
|
|
571
|
+
* too would make one field shout twice.
|
|
572
|
+
*/
|
|
573
|
+
subLabel: {
|
|
574
|
+
fontSize: number;
|
|
575
|
+
letterSpacing: number;
|
|
576
|
+
};
|
|
577
|
+
/** Positioning context for a floating `AnchoredMenu` (`position:absolute; top:100%`). */
|
|
578
|
+
anchor: {
|
|
579
|
+
position: "relative";
|
|
580
|
+
};
|
|
581
|
+
menu: {
|
|
582
|
+
position: "absolute";
|
|
583
|
+
top: "100%";
|
|
584
|
+
left: number;
|
|
585
|
+
marginTop: number;
|
|
586
|
+
minWidth: number;
|
|
587
|
+
maxHeight: number;
|
|
588
|
+
borderWidth: number;
|
|
589
|
+
borderRadius: number;
|
|
590
|
+
paddingVertical: number;
|
|
591
|
+
zIndex: number;
|
|
592
|
+
boxShadow: string;
|
|
593
|
+
elevation: number;
|
|
594
|
+
overflow: "hidden";
|
|
595
|
+
};
|
|
596
|
+
option: {
|
|
597
|
+
paddingHorizontal: number;
|
|
598
|
+
paddingVertical: number;
|
|
599
|
+
};
|
|
600
|
+
optionText: {
|
|
601
|
+
fontSize: number;
|
|
602
|
+
};
|
|
603
|
+
error: {
|
|
604
|
+
fontSize: number;
|
|
605
|
+
marginTop: number;
|
|
606
|
+
};
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* `suggestOptions` — the ranked substring matcher behind `TypeaheadControl`, generalized from
|
|
611
|
+
* aml-v2's `suggestCountries` and promoted verbatim out of `@dloizides/ui-tables`' private
|
|
612
|
+
* `Filters/utils/suggest.ts`.
|
|
613
|
+
*
|
|
614
|
+
* Ranks: value exact (0) > value prefix (1) > label prefix (2) > label contains (3); ties broken
|
|
615
|
+
* by `label.localeCompare`. Empty/short queries return `[]` — nothing surfaces until `minChars`
|
|
616
|
+
* is typed, mirroring a native `<datalist>`.
|
|
617
|
+
*/
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Rank + cap the options matching `query`. Returns `[]` until `query` (trimmed) is at least
|
|
621
|
+
* `minChars` long, then the best `limit` matches, ranked as documented above.
|
|
622
|
+
*/
|
|
623
|
+
declare function suggestOptions(options: readonly ControlOption[], query: string, minChars: number, limit: number): readonly ControlOption[];
|
|
624
|
+
/** True when `text` is non-empty yet matches no option's value or label exactly (case-insensitive). */
|
|
625
|
+
declare function isUnmatched(options: readonly ControlOption[], text: string): boolean;
|
|
626
|
+
|
|
627
|
+
export { AnchoredMenu, type AnchoredMenuColors, type AnchoredMenuProps, type ChipOption, ChipSelector, type ChipSelectorProps, type ChipVariant, type ControlOption, DEFAULT_OPTIONAL_LABEL, DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS, DEFAULT_TYPEAHEAD_MIN_CHARS, DateRangeControl, type DateRangeControlProps, type DateRangeValue, Field, type FieldChildContext, type FieldChildren, type FieldLabelVariant, type FieldMarker, type FieldProps, FormActions, type FormActionsProps, FormCheckbox, type FormCheckboxProps, FormField, type FormFieldProps, FormSwitch, type FormSwitchProps, SelectControl, type SelectControlProps, type ThemedInput, ThemedTextInput, type ThemedTextInputProps, TypeaheadControl, type TypeaheadControlProps, type UseThemedInputOptions, controlStyles, isUnmatched, suggestOptions, useThemedInput };
|