@colixsystems/widget-sdk 0.245.0 → 0.247.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/README.md +60 -2
- package/dist/button-tokens.js +154 -0
- package/dist/button-view.js +251 -93
- package/dist/button.js +5 -3
- package/dist/button.native.js +6 -4
- package/dist/chart-logic.js +575 -0
- package/dist/chart-tokens.js +131 -0
- package/dist/chart-view.js +262 -0
- package/dist/chart.js +21 -0
- package/dist/chart.native.js +10 -0
- package/dist/contract.cjs +132 -35
- package/dist/contract.js +132 -35
- package/dist/detail-parts-view.js +31 -2
- package/dist/file-image-logic.js +162 -0
- package/dist/file-image-source.js +71 -0
- package/dist/file-image-view.js +119 -0
- package/dist/file-image.js +8 -0
- package/dist/file-image.native.js +8 -0
- package/dist/form-control-logic.js +23 -0
- package/dist/form-control-tokens.js +25 -10
- package/dist/grid-logic.js +222 -0
- package/dist/grid-view.js +109 -0
- package/dist/grid.js +7 -0
- package/dist/grid.native.js +7 -0
- package/dist/host.d.ts +6 -0
- package/dist/host.js +2 -0
- package/dist/index.d.ts +481 -20
- package/dist/index.js +14 -1
- package/dist/index.native.js +14 -1
- package/dist/menu-view.js +168 -0
- package/dist/overlay-tokens.js +50 -0
- package/dist/overlay-view.js +67 -24
- package/dist/overlay.native.js +3 -1
- package/dist/people-picker-logic.js +203 -0
- package/dist/people-picker-view.js +247 -0
- package/dist/people-picker.js +11 -0
- package/dist/people-picker.native.js +9 -0
- package/dist/popover-tokens.js +145 -0
- package/dist/popover-view.js +252 -0
- package/dist/popover.js +23 -0
- package/dist/popover.native.js +22 -0
- package/dist/radio-group-logic.js +61 -0
- package/dist/radio-group-tokens.js +62 -0
- package/dist/radio-group-view.js +262 -0
- package/dist/radio-group.js +12 -0
- package/dist/radio-group.native.js +7 -0
- package/dist/select-search-logic.js +150 -0
- package/dist/select-view.js +255 -43
- package/dist/select.js +6 -2
- package/dist/select.native.js +5 -3
- package/dist/tabs-tokens.js +59 -0
- package/dist/tabs-view.js +9 -43
- package/dist/tooltip-view.js +137 -0
- package/dist/web-modal.js +95 -23
- package/package.json +1 -1
- package/src/contract.js +132 -35
package/dist/index.d.ts
CHANGED
|
@@ -2406,6 +2406,60 @@ export const WIDE_WIDTH_PX: number;
|
|
|
2406
2406
|
*/
|
|
2407
2407
|
export function widthTier(width: number): "narrow" | "medium" | "wide";
|
|
2408
2408
|
|
|
2409
|
+
/** How a `<Grid>` splits its cells into lines. */
|
|
2410
|
+
export type GridBalance = "cards" | "tiles";
|
|
2411
|
+
|
|
2412
|
+
/** A theme spacing name, or a number of pixels. */
|
|
2413
|
+
export type GridGap = "xs" | "sm" | "md" | "lg" | "xl" | number;
|
|
2414
|
+
|
|
2415
|
+
/**
|
|
2416
|
+
* Lays its children out in balanced lines of cells, sized from the grid's own
|
|
2417
|
+
* measured width, on the web Player and the native export alike. It measures
|
|
2418
|
+
* an inner box with no padding, so a `style` padding is not counted twice.
|
|
2419
|
+
*
|
|
2420
|
+
* - `balance="cards"` (default): as many cells per line as fit at
|
|
2421
|
+
* `minCellWidth` (240 when unset); every line but the last is full, and the
|
|
2422
|
+
* last is padded with empty cells so its cards keep the width of the lines
|
|
2423
|
+
* above. 6 that fit 5 are 3 + 3.
|
|
2424
|
+
* - `balance="tiles"`: the remainder spreads over every line and each line
|
|
2425
|
+
* stretches, so 5 tiles at 4 per line are 3 + 2, never 4 + 1. The per-line
|
|
2426
|
+
* ceiling is `maxColumns`, or what fits at `minCellWidth`, or else 4 / 3 / 2
|
|
2427
|
+
* for the wide / medium / narrow width tier.
|
|
2428
|
+
* - `columns`: exactly that many cells per line, the last line padded.
|
|
2429
|
+
* - `cell={{ min, max }}`: definite-size cells (calendar days, seats,
|
|
2430
|
+
* swatches) as large as fit up to `max`, never below `min` (32 when unset),
|
|
2431
|
+
* in a block centred in the grid (a block whose `min` cells cannot fit
|
|
2432
|
+
* starts at the leading edge, so only its far end is cut off); with
|
|
2433
|
+
* `columns` a fixed count per line. `square` makes each cell as tall as it
|
|
2434
|
+
* is wide.
|
|
2435
|
+
*
|
|
2436
|
+
* Each child is one cell and keeps its own look; a child with `flex: 1` fills
|
|
2437
|
+
* its cell's height, so a line of cards ends level. Nothing is drawn until the
|
|
2438
|
+
* width is measured when the layout depends on it. In a row, give the grid
|
|
2439
|
+
* `style={{ flex: 1, minWidth: 0 }}` so it has a width to measure.
|
|
2440
|
+
*
|
|
2441
|
+
* @example
|
|
2442
|
+
* <Grid minCellWidth={240}>{items.map((item) => <Card key={item.id}>…</Card>)}</Grid>
|
|
2443
|
+
* <Grid columns={7} cell={{ min: 32, max: 64 }} square gap="xs">{days}</Grid>
|
|
2444
|
+
*/
|
|
2445
|
+
export const Grid: (props: {
|
|
2446
|
+
children?: ReactNode;
|
|
2447
|
+
balance?: GridBalance;
|
|
2448
|
+
/** The narrowest a cell may be; the per-line count is derived from it. */
|
|
2449
|
+
minCellWidth?: number;
|
|
2450
|
+
maxColumns?: number;
|
|
2451
|
+
columns?: number;
|
|
2452
|
+
cell?: { min?: number; max: number };
|
|
2453
|
+
square?: boolean;
|
|
2454
|
+
/** Space between cells and lines; `"md"` when unset. */
|
|
2455
|
+
gap?: GridGap;
|
|
2456
|
+
/** The grid's outer box; padding here stays out of the measured width. */
|
|
2457
|
+
style?: any;
|
|
2458
|
+
testID?: string;
|
|
2459
|
+
/** Names the grid as one group to a screen reader. */
|
|
2460
|
+
accessibilityLabel?: string;
|
|
2461
|
+
}) => any;
|
|
2462
|
+
|
|
2409
2463
|
/** Pass-through options for `useGeolocation().getCurrentPosition(...)`. */
|
|
2410
2464
|
export interface GeolocationOptions {
|
|
2411
2465
|
enableHighAccuracy?: boolean;
|
|
@@ -3140,6 +3194,8 @@ export interface AppUserGroupRow {
|
|
|
3140
3194
|
|
|
3141
3195
|
export interface GroupsQuery {
|
|
3142
3196
|
q?: string;
|
|
3197
|
+
/** Only these groups (1 to 100 ids): name the groups behind ids you hold. */
|
|
3198
|
+
ids?: string[];
|
|
3143
3199
|
limit?: number;
|
|
3144
3200
|
offset?: number;
|
|
3145
3201
|
}
|
|
@@ -3870,6 +3926,11 @@ export const Avatar: (props: {
|
|
|
3870
3926
|
seed?: string;
|
|
3871
3927
|
/** An absolute image URL. */
|
|
3872
3928
|
url?: string;
|
|
3929
|
+
/**
|
|
3930
|
+
* A filestore file id (a FILE column's value). Takes precedence over `url`;
|
|
3931
|
+
* the initials show while it loads and stay if it cannot load.
|
|
3932
|
+
*/
|
|
3933
|
+
fileId?: string | null;
|
|
3873
3934
|
/** A size token, or a number of px (clamped to 16-160). */
|
|
3874
3935
|
size?: "sm" | "md" | "lg" | "xl" | number;
|
|
3875
3936
|
shape?: "circle" | "rounded";
|
|
@@ -3878,6 +3939,36 @@ export const Avatar: (props: {
|
|
|
3878
3939
|
testID?: string;
|
|
3879
3940
|
}) => any;
|
|
3880
3941
|
|
|
3942
|
+
/**
|
|
3943
|
+
* A stored file's picture, or one at a URL: a themed `<Skeleton>` while it
|
|
3944
|
+
* loads and a fallback, never a broken image, when it cannot. A `fileId` is
|
|
3945
|
+
* resolved through `useFilestoreFile`, and an expired signed URL is fetched
|
|
3946
|
+
* again once before the fallback shows.
|
|
3947
|
+
*
|
|
3948
|
+
* @example
|
|
3949
|
+
* <FileImage fileId={record.Photo} variant="card" aspectRatio={4 / 3} />
|
|
3950
|
+
*/
|
|
3951
|
+
export const FileImage: (props: {
|
|
3952
|
+
/** A filestore file id (a FILE column's value). Wins over `uri`. */
|
|
3953
|
+
fileId?: string | null;
|
|
3954
|
+
/** A URL you already have, e.g. a `useFilestoreFiles()` row's `urls.card`. */
|
|
3955
|
+
uri?: string | null;
|
|
3956
|
+
/** The size-ladder rung to load. Default "large". */
|
|
3957
|
+
variant?: "thumbnail" | "card" | "large" | "hero" | "original";
|
|
3958
|
+
/** Width / height. Unset, the box takes the picture's own shape once loaded. */
|
|
3959
|
+
aspectRatio?: number;
|
|
3960
|
+
/** Corner radius: px, a theme radius name, or "none". Default the theme's `md`. */
|
|
3961
|
+
radius?: number | "none" | "sm" | "md" | "lg" | "pill";
|
|
3962
|
+
resizeMode?: "cover" | "contain" | "stretch" | "center";
|
|
3963
|
+
/** What shows when the picture cannot load. Default "icon". */
|
|
3964
|
+
fallback?: "icon" | "blank";
|
|
3965
|
+
/** Unset, the picture is decorative and hidden from assistive technology. */
|
|
3966
|
+
accessibilityLabel?: string;
|
|
3967
|
+
style?: any;
|
|
3968
|
+
/** Also tags `<testID>-image`, `<testID>-loading` and `<testID>-fallback`. */
|
|
3969
|
+
testID?: string;
|
|
3970
|
+
}) => any;
|
|
3971
|
+
|
|
3881
3972
|
/** Themed completion bar or ring for real progress toward a known goal. */
|
|
3882
3973
|
export const Progress: (props: {
|
|
3883
3974
|
/** Percent complete; clamped to 0-100. */
|
|
@@ -3979,38 +4070,61 @@ export const Card: (props: {
|
|
|
3979
4070
|
export type CardScrim = "bottom" | "top" | "left" | "right" | "full" | "none";
|
|
3980
4071
|
export type CardImagePosition = "center" | "top" | "bottom" | "left" | "right";
|
|
3981
4072
|
|
|
3982
|
-
export type ButtonVariant = "primary" | "secondary" | "outlined" | "danger";
|
|
4073
|
+
export type ButtonVariant = "primary" | "secondary" | "outlined" | "danger" | "ghost" | "link";
|
|
4074
|
+
export type ButtonSize = "sm" | "md" | "lg";
|
|
3983
4075
|
export const BUTTON_VARIANTS: readonly ButtonVariant[];
|
|
3984
4076
|
|
|
4077
|
+
/** Per-button surface fields; unset ones follow the theme. */
|
|
4078
|
+
export interface ButtonFields {
|
|
4079
|
+
background?: string;
|
|
4080
|
+
textColor?: string;
|
|
4081
|
+
borderColor?: string;
|
|
4082
|
+
borderWidth?: number;
|
|
4083
|
+
paddingX?: number;
|
|
4084
|
+
paddingY?: number;
|
|
4085
|
+
radius?: number;
|
|
4086
|
+
fontWeight?: string;
|
|
4087
|
+
fontSize?: number;
|
|
4088
|
+
shadow?: "none" | "sm" | "md" | "lg";
|
|
4089
|
+
gradient?: { from: string; to: string; angle?: number };
|
|
4090
|
+
}
|
|
4091
|
+
|
|
3985
4092
|
/**
|
|
3986
4093
|
* Themed button (Design > Components > Buttons, Danger buttons, Button outline). Omit
|
|
3987
|
-
* `onPress` for a purely visual button inside something pressable.
|
|
4094
|
+
* `onPress` for a purely visual button inside something pressable. `ghost` and
|
|
4095
|
+
* `link` draw no fill or border and take only the look's shape and type.
|
|
3988
4096
|
*
|
|
3989
4097
|
* @example
|
|
3990
|
-
* <Button title="Save" onPress={save} />
|
|
4098
|
+
* <Button title="Save" onPress={save} busy={saving} />
|
|
3991
4099
|
* <Button title="Delete" variant="danger" icon="trash-2" onPress={remove} />
|
|
4100
|
+
* <Button title="Load more" variant="ghost" size="sm" onPress={next} />
|
|
3992
4101
|
*/
|
|
3993
|
-
|
|
4102
|
+
/**
|
|
4103
|
+
* What a `<Menu>`, `<Popover>` or `<Tooltip>` puts on the button it wraps, so
|
|
4104
|
+
* a button can open one and expose whether it is open.
|
|
4105
|
+
*/
|
|
4106
|
+
export interface ButtonTriggerProps {
|
|
4107
|
+
/** A `<Tooltip>` shows on a long press. */
|
|
4108
|
+
onLongPress?: () => void;
|
|
4109
|
+
"aria-haspopup"?: "menu" | "dialog" | boolean;
|
|
4110
|
+
"aria-expanded"?: boolean;
|
|
4111
|
+
"aria-describedby"?: string;
|
|
4112
|
+
}
|
|
4113
|
+
|
|
4114
|
+
export const Button: (props: ButtonTriggerProps & {
|
|
3994
4115
|
title: ReactNode;
|
|
3995
4116
|
variant?: ButtonVariant;
|
|
4117
|
+
/** sm (36 high) | md (44, default) | lg (52). */
|
|
4118
|
+
size?: ButtonSize;
|
|
3996
4119
|
icon?: string;
|
|
3997
4120
|
iconPosition?: "leading" | "trailing";
|
|
3998
4121
|
onPress?: () => void;
|
|
3999
4122
|
disabled?: boolean;
|
|
4000
|
-
/**
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
borderWidth?: number;
|
|
4006
|
-
paddingX?: number;
|
|
4007
|
-
paddingY?: number;
|
|
4008
|
-
radius?: number;
|
|
4009
|
-
fontWeight?: string;
|
|
4010
|
-
fontSize?: number;
|
|
4011
|
-
shadow?: "none" | "sm" | "md" | "lg";
|
|
4012
|
-
gradient?: { from: string; to: string; angle?: number };
|
|
4013
|
-
};
|
|
4123
|
+
/** A pending action: a spinner over the kept label; it cannot be pressed. */
|
|
4124
|
+
busy?: boolean;
|
|
4125
|
+
/** A toggle's on/off state; omit for a plain button. */
|
|
4126
|
+
selected?: boolean;
|
|
4127
|
+
fields?: ButtonFields;
|
|
4014
4128
|
style?: any;
|
|
4015
4129
|
labelStyle?: any;
|
|
4016
4130
|
accessibilityLabel?: string;
|
|
@@ -4019,6 +4133,34 @@ export const Button: (props: {
|
|
|
4019
4133
|
ref?: { current: any } | ((node: any) => void);
|
|
4020
4134
|
}) => any;
|
|
4021
4135
|
|
|
4136
|
+
/**
|
|
4137
|
+
* A square themed button that shows only an icon, at least 36px on both hosts.
|
|
4138
|
+
* `accessibilityLabel` is its only name, so it is required.
|
|
4139
|
+
*
|
|
4140
|
+
* @example
|
|
4141
|
+
* <IconButton icon="pencil" accessibilityLabel="Edit order" onPress={edit} />
|
|
4142
|
+
* <IconButton icon="bold" accessibilityLabel="Bold" selected={bold} onPress={toggleBold} />
|
|
4143
|
+
*/
|
|
4144
|
+
export const IconButton: (props: ButtonTriggerProps & {
|
|
4145
|
+
/** A lucide icon name, drawn with `<Icon>`. */
|
|
4146
|
+
icon: string;
|
|
4147
|
+
accessibilityLabel: string;
|
|
4148
|
+
/** ghost (default) | primary | secondary | outlined | danger. */
|
|
4149
|
+
variant?: Exclude<ButtonVariant, "link">;
|
|
4150
|
+
/** sm (36) | md (44, default) | lg (52). */
|
|
4151
|
+
size?: ButtonSize;
|
|
4152
|
+
/** The glyph's colour, over the variant's. */
|
|
4153
|
+
color?: string;
|
|
4154
|
+
onPress?: () => void;
|
|
4155
|
+
disabled?: boolean;
|
|
4156
|
+
busy?: boolean;
|
|
4157
|
+
selected?: boolean;
|
|
4158
|
+
fields?: ButtonFields;
|
|
4159
|
+
style?: any;
|
|
4160
|
+
testID?: string;
|
|
4161
|
+
ref?: { current: any } | ((node: any) => void);
|
|
4162
|
+
}) => any;
|
|
4163
|
+
|
|
4022
4164
|
/**
|
|
4023
4165
|
* What every form control shares: the label drawn with it (and read by a
|
|
4024
4166
|
* screen reader), a hint below it, and an error that replaces the hint and
|
|
@@ -4101,12 +4243,53 @@ export interface SelectOption<V extends string | number = string | number> {
|
|
|
4101
4243
|
label: string;
|
|
4102
4244
|
disabled?: boolean;
|
|
4103
4245
|
testID?: string;
|
|
4246
|
+
/** Drawn before the label in the sheet: an `<Avatar>`, an icon. */
|
|
4247
|
+
leading?: ReactNode;
|
|
4248
|
+
}
|
|
4249
|
+
|
|
4250
|
+
/**
|
|
4251
|
+
* The searchable mode of `<Select>`: a `<SearchField>` heads the sheet. Turn
|
|
4252
|
+
* it on with `searchable` (the options are filtered where they are held),
|
|
4253
|
+
* `onSearch` (you fetch per query) or async `options` (Select fetches).
|
|
4254
|
+
*/
|
|
4255
|
+
export interface SelectSearchProps<V extends string | number = string | number> {
|
|
4256
|
+
/** Filter the given `options` by label as the person types. */
|
|
4257
|
+
searchable?: boolean;
|
|
4258
|
+
/**
|
|
4259
|
+
* Called with the trimmed query when the sheet opens ("") and once typing
|
|
4260
|
+
* pauses; answer by passing new `options` (and `loading` meanwhile).
|
|
4261
|
+
*/
|
|
4262
|
+
onSearch?: (query: string) => void;
|
|
4263
|
+
/** The pause, in ms, before a typed query is sent. Default 250. */
|
|
4264
|
+
searchDebounceMs?: number;
|
|
4265
|
+
/** The options for the last query are on their way. */
|
|
4266
|
+
loading?: boolean;
|
|
4267
|
+
/** The last query failed; a string replaces `loadErrorText`. */
|
|
4268
|
+
optionsError?: boolean | string;
|
|
4269
|
+
/**
|
|
4270
|
+
* The options behind picked values the current `options` may not hold (a
|
|
4271
|
+
* saved choice outside the first page), so the trigger names them.
|
|
4272
|
+
*/
|
|
4273
|
+
selectedOptions?: Array<SelectOption<V>>;
|
|
4274
|
+
/** Default "Search". */
|
|
4275
|
+
searchPlaceholder?: string;
|
|
4276
|
+
/** Shown when a query finds nothing. Default "No results". */
|
|
4277
|
+
noResultsText?: string;
|
|
4278
|
+
/** Default "Loading…". */
|
|
4279
|
+
loadingText?: string;
|
|
4280
|
+
/** Default "Could not load the options". */
|
|
4281
|
+
loadErrorText?: string;
|
|
4104
4282
|
}
|
|
4105
4283
|
|
|
4106
4284
|
/** What every `<Select>` takes, in either mode. */
|
|
4107
4285
|
export type SelectBaseProps<V extends string | number = string | number> = FormControlProps &
|
|
4108
|
-
FormFieldOverrides &
|
|
4109
|
-
|
|
4286
|
+
FormFieldOverrides &
|
|
4287
|
+
SelectSearchProps<V> & {
|
|
4288
|
+
/**
|
|
4289
|
+
* The options, or a function Select calls with each query (searchable
|
|
4290
|
+
* mode) that resolves to them; only its latest answer is shown.
|
|
4291
|
+
*/
|
|
4292
|
+
options: Array<SelectOption<V>> | ((query: string) => Promise<Array<SelectOption<V>>>);
|
|
4110
4293
|
/** Shown while nothing is chosen. Default "Select". */
|
|
4111
4294
|
placeholder?: string;
|
|
4112
4295
|
/** The sheet's heading. Defaults to a text `label`. */
|
|
@@ -4134,6 +4317,11 @@ export type SelectBaseProps<V extends string | number = string | number> = FormC
|
|
|
4134
4317
|
* trigger shows the picked labels as small chips while they fit on its line,
|
|
4135
4318
|
* else "N selected".
|
|
4136
4319
|
*
|
|
4320
|
+
* Searchable (`searchable`, `onSearch` or async `options`), the sheet leads
|
|
4321
|
+
* with a `<SearchField>`, says when it is loading and when nothing matches,
|
|
4322
|
+
* and keeps the label of every option it has shown; its rows take the theme's
|
|
4323
|
+
* Lists row height and padding when they are set.
|
|
4324
|
+
*
|
|
4137
4325
|
* @example
|
|
4138
4326
|
* <Select label="Status" value={status} onValueChange={setStatus}
|
|
4139
4327
|
* options={[{ value: "open", label: "Open" }, { value: "done", label: "Done" }]} />
|
|
@@ -4160,6 +4348,62 @@ export const Select: <V extends string | number = string | number>(
|
|
|
4160
4348
|
}),
|
|
4161
4349
|
) => any;
|
|
4162
4350
|
|
|
4351
|
+
/** Where `<PeoplePicker>` reads its options. */
|
|
4352
|
+
export type PeoplePickerSource = "users" | "groups" | "records";
|
|
4353
|
+
|
|
4354
|
+
/**
|
|
4355
|
+
* A searchable `<Select>` of the workspace's users (`useDirectory`, scope
|
|
4356
|
+
* `directory.read:users`), its groups (`useGroups`, `groups.read:*`) or one
|
|
4357
|
+
* table's records (`useDatastoreQuery`, the table's `datastore.read` scope).
|
|
4358
|
+
* Nothing loads until the sheet opens; each pause in typing searches on the
|
|
4359
|
+
* server. A saved value the page does not hold is looked up once by id, so the
|
|
4360
|
+
* trigger shows its name, `loadingText` meanwhile, or `unknownText` when it is
|
|
4361
|
+
* gone, never the id. Every other `<Select>` prop works.
|
|
4362
|
+
*
|
|
4363
|
+
* @example
|
|
4364
|
+
* <PeoplePicker label="Assignee" value={assignee} onValueChange={setAssignee} />
|
|
4365
|
+
* <PeoplePicker source="groups" multiple label="Teams" values={teams} onValuesChange={setTeams} />
|
|
4366
|
+
* <PeoplePicker source="records" table={tableId} label="Customer" value={customerId}
|
|
4367
|
+
* onValueChange={setCustomerId} />
|
|
4368
|
+
*/
|
|
4369
|
+
export const PeoplePicker: (
|
|
4370
|
+
props: Omit<SelectBaseProps<string>, "options" | "onSearch" | "selectedOptions" | "searchable"> & {
|
|
4371
|
+
/** Default "users". */
|
|
4372
|
+
source?: PeoplePickerSource;
|
|
4373
|
+
/** `source="records"`: the table id. */
|
|
4374
|
+
table?: string;
|
|
4375
|
+
/** `source="records"`: the column that names a record. Default the identification column. */
|
|
4376
|
+
labelColumn?: string;
|
|
4377
|
+
/** `source="records"`: a FILE column drawn as each row's avatar. */
|
|
4378
|
+
avatarColumn?: string;
|
|
4379
|
+
/** `source="users"`: only members of this group (a `useGroups()` row id). */
|
|
4380
|
+
groupId?: string;
|
|
4381
|
+
/** `source="records"`: narrows the rows, as `useDatastoreQuery`'s `filter`. */
|
|
4382
|
+
filter?: Query["filter"];
|
|
4383
|
+
/** Ids never offered (already members, the signed-in user). */
|
|
4384
|
+
excludeIds?: string[];
|
|
4385
|
+
/** Rows per search. Default 50, at most 200. */
|
|
4386
|
+
pageSize?: number;
|
|
4387
|
+
/** Draw an avatar before each user or group. Default true. */
|
|
4388
|
+
showAvatars?: boolean;
|
|
4389
|
+
/** A saved value whose row is gone, or a row with no name. Default "Unknown". */
|
|
4390
|
+
unknownText?: string;
|
|
4391
|
+
} & (
|
|
4392
|
+
| {
|
|
4393
|
+
multiple?: false;
|
|
4394
|
+
value?: string | null;
|
|
4395
|
+
onValueChange?: (value: string, option: SelectOption<string>) => void;
|
|
4396
|
+
}
|
|
4397
|
+
| {
|
|
4398
|
+
multiple: true;
|
|
4399
|
+
values?: string[] | null;
|
|
4400
|
+
onValuesChange?: (values: string[], options: Array<SelectOption<string>>) => void;
|
|
4401
|
+
selectedCountText?: (count: number) => string;
|
|
4402
|
+
doneText?: string;
|
|
4403
|
+
}
|
|
4404
|
+
),
|
|
4405
|
+
) => any;
|
|
4406
|
+
|
|
4163
4407
|
/**
|
|
4164
4408
|
* Space-key activation for a control whose role is not a button: on the web a
|
|
4165
4409
|
* `Pressable` answers Space only for a button. Native ignores `onKeyDown`.
|
|
@@ -4204,6 +4448,48 @@ export const SearchField: (props: FormControlProps & {
|
|
|
4204
4448
|
[prop: string]: any;
|
|
4205
4449
|
}) => any;
|
|
4206
4450
|
|
|
4451
|
+
export type RadioGroupVariant = "list" | "card" | "segmented";
|
|
4452
|
+
|
|
4453
|
+
export interface RadioOption<V extends string | number = string | number> {
|
|
4454
|
+
value: V;
|
|
4455
|
+
label: ReactNode;
|
|
4456
|
+
/** A second line under the label; not drawn by the segmented variant. */
|
|
4457
|
+
description?: ReactNode;
|
|
4458
|
+
/** A lucide icon name drawn before the label. */
|
|
4459
|
+
icon?: string;
|
|
4460
|
+
disabled?: boolean;
|
|
4461
|
+
accessibilityLabel?: string;
|
|
4462
|
+
testID?: string;
|
|
4463
|
+
}
|
|
4464
|
+
|
|
4465
|
+
/**
|
|
4466
|
+
* Themed pick-ONE of a short list that stays on screen. `list` (default) is
|
|
4467
|
+
* the app's input panel with one row per option, `card` one bordered card per
|
|
4468
|
+
* option (with its `description`), both from Design > Components > Inputs;
|
|
4469
|
+
* `segmented` is the segmented tab strip from Design > Components > Tabs,
|
|
4470
|
+
* its options sharing the row evenly. Radio role and checked state on both
|
|
4471
|
+
* hosts; on the web the group is one tab stop, the arrow keys move the
|
|
4472
|
+
* choice and Space picks the focused option. Other props land on the group.
|
|
4473
|
+
*
|
|
4474
|
+
* @example
|
|
4475
|
+
* <RadioGroup label="Delivery" value={speed} onValueChange={setSpeed}
|
|
4476
|
+
* options={[{ value: "standard", label: "Standard" }, { value: "express", label: "Express" }]} />
|
|
4477
|
+
*/
|
|
4478
|
+
export const RadioGroup: <V extends string | number = string | number>(
|
|
4479
|
+
props: FormControlProps & {
|
|
4480
|
+
options: Array<RadioOption<V>>;
|
|
4481
|
+
value?: V | null;
|
|
4482
|
+
/** Called when a different option is picked. */
|
|
4483
|
+
onValueChange?: (value: V, option: RadioOption<V>) => void;
|
|
4484
|
+
variant?: RadioGroupVariant;
|
|
4485
|
+
/** The group. */
|
|
4486
|
+
style?: any;
|
|
4487
|
+
/** The box around a group that shows a label, helper or error. */
|
|
4488
|
+
containerStyle?: any;
|
|
4489
|
+
[prop: string]: any;
|
|
4490
|
+
},
|
|
4491
|
+
) => any;
|
|
4492
|
+
|
|
4207
4493
|
export type TabStyle = "segmented" | "pill" | "underline";
|
|
4208
4494
|
|
|
4209
4495
|
/**
|
|
@@ -4334,6 +4620,80 @@ export const ChipGroup: (props: {
|
|
|
4334
4620
|
testID?: string;
|
|
4335
4621
|
}) => any;
|
|
4336
4622
|
|
|
4623
|
+
export type ChartType = "bar" | "hbar" | "line" | "area" | "donut" | "sparkline";
|
|
4624
|
+
export type ChartValueFormat = "number" | "compact" | "percent" | ((value: number) => string);
|
|
4625
|
+
|
|
4626
|
+
/** One series of a multi-series `<Chart>`: the key each `data` item carries its value under. */
|
|
4627
|
+
export interface ChartSeries {
|
|
4628
|
+
key: string;
|
|
4629
|
+
label: string;
|
|
4630
|
+
/** A colour of the series' own; leave unset so the theme's chart look applies. */
|
|
4631
|
+
color?: string;
|
|
4632
|
+
}
|
|
4633
|
+
|
|
4634
|
+
/**
|
|
4635
|
+
* Themed chart drawn with react-native-svg. Its series colours, axis and label
|
|
4636
|
+
* colour, gridline colour and bar corners come from the theme's `chart` scope
|
|
4637
|
+
* (falling back to the theme's colours), so every chart in the app matches. It
|
|
4638
|
+
* measures its own width, shows a `<Skeleton>` while `loading` and an
|
|
4639
|
+
* `<EmptyState>` when there is nothing to plot, draws a legend for a donut and
|
|
4640
|
+
* for several series, and gives a screen reader a summary and the values.
|
|
4641
|
+
*
|
|
4642
|
+
* @example
|
|
4643
|
+
* const { groups, loading } = useDatastoreAggregate(tableId, { groupBy: "city", sumColumn: "visits" });
|
|
4644
|
+
* <Chart type="bar" loading={loading}
|
|
4645
|
+
* data={groups.map((g) => ({ label: String(g.group), value: Number(g.sum) || 0 }))} />
|
|
4646
|
+
*/
|
|
4647
|
+
export const Chart: (props: {
|
|
4648
|
+
/** Default "bar". "hbar" is horizontal bars; "sparkline" a small line with no axes. */
|
|
4649
|
+
type?: ChartType;
|
|
4650
|
+
/** `[{ label, value }]`, or with `series` one number per series key. */
|
|
4651
|
+
data: Array<{ label: string | number | { label: string }; [key: string]: unknown }>;
|
|
4652
|
+
/** Several series sharing `data`. A donut and a sparkline draw the first. */
|
|
4653
|
+
series?: ChartSeries[];
|
|
4654
|
+
/**
|
|
4655
|
+
* How values read on the axis, the legend and to a screen reader, grouped
|
|
4656
|
+
* for the app's language. Default "number". "percent" appends "%" to values
|
|
4657
|
+
* already in percent (42 reads "42%"); it does not multiply by 100.
|
|
4658
|
+
*/
|
|
4659
|
+
valueFormat?: ChartValueFormat;
|
|
4660
|
+
/** The plot's height in px. Default 220, or 48 for a sparkline. */
|
|
4661
|
+
height?: number;
|
|
4662
|
+
loading?: boolean;
|
|
4663
|
+
/** Defaults to the shared "No results" text. */
|
|
4664
|
+
emptyTitle?: string;
|
|
4665
|
+
emptyMessage?: string;
|
|
4666
|
+
/** Replaces the spoken summary sentence; the values are still read after it. */
|
|
4667
|
+
accessibilityLabel?: string;
|
|
4668
|
+
/** The tail of a spoken value list cut short; default `(count) => \`and ${count} more\``. */
|
|
4669
|
+
moreText?: (count: number) => string;
|
|
4670
|
+
/** For hosts rendering outside a widget context; widgets omit it. */
|
|
4671
|
+
theme?: any;
|
|
4672
|
+
style?: any;
|
|
4673
|
+
testID?: string;
|
|
4674
|
+
}) => any;
|
|
4675
|
+
|
|
4676
|
+
/**
|
|
4677
|
+
* The colours `<Chart>` paints with, for a chart a widget draws itself (a
|
|
4678
|
+
* scatter plot, a timeline) so it matches Design > Components > Charts.
|
|
4679
|
+
*
|
|
4680
|
+
* @example
|
|
4681
|
+
* const colors = chartColors(useTheme());
|
|
4682
|
+
* <Circle fill={colors.series(0)} fillOpacity={colors.seriesOpacity(0)} />
|
|
4683
|
+
*/
|
|
4684
|
+
export function chartColors(theme: any): {
|
|
4685
|
+
/** The six series colours, in order. */
|
|
4686
|
+
palette: string[];
|
|
4687
|
+
/** Axis line and label colour. */
|
|
4688
|
+
axis: string;
|
|
4689
|
+
/** Gridline colour. */
|
|
4690
|
+
grid: string;
|
|
4691
|
+
/** Series `index`'s colour; a seventh and later one is lighter. */
|
|
4692
|
+
series(index: number): string;
|
|
4693
|
+
/** Series `index`'s opacity: 1, below 1 for a repeat of a colour that cannot be lightened. */
|
|
4694
|
+
seriesOpacity(index: number): number;
|
|
4695
|
+
};
|
|
4696
|
+
|
|
4337
4697
|
/**
|
|
4338
4698
|
* A file as `<FilePicker>` and `<FileUpload>` hand it over: the browser's
|
|
4339
4699
|
* `File` on the web, expo-file-system's `File` on the Expo export. Pass it to
|
|
@@ -4429,6 +4789,107 @@ export const FileUpload: (props: FormControlProps & {
|
|
|
4429
4789
|
containerStyle?: any;
|
|
4430
4790
|
}) => any;
|
|
4431
4791
|
|
|
4792
|
+
export type PopoverPlacement = "bottom" | "top";
|
|
4793
|
+
|
|
4794
|
+
/** One `<Menu>` item. */
|
|
4795
|
+
export interface MenuItem {
|
|
4796
|
+
label: string;
|
|
4797
|
+
/** Runs after the menu closes. */
|
|
4798
|
+
onPress?: () => void;
|
|
4799
|
+
/** A Lucide icon name, or an element drawn before the label. */
|
|
4800
|
+
icon?: string | ReactNode;
|
|
4801
|
+
/** Drawn in the theme's danger colour. */
|
|
4802
|
+
danger?: boolean;
|
|
4803
|
+
/** Dimmed, skipped by the arrow keys, and cannot be picked. */
|
|
4804
|
+
disabled?: boolean;
|
|
4805
|
+
accessibilityLabel?: string;
|
|
4806
|
+
testID?: string;
|
|
4807
|
+
key?: string;
|
|
4808
|
+
}
|
|
4809
|
+
|
|
4810
|
+
/**
|
|
4811
|
+
* A list of actions opened from a trigger: a row's "…" button, a toolbar's
|
|
4812
|
+
* overflow. Beside the trigger on a wide screen, a bottom sheet on a phone;
|
|
4813
|
+
* drawn over the screen, so no card or list clips it. The backdrop, Escape
|
|
4814
|
+
* (web) and the Android back button close it, and focus returns to the
|
|
4815
|
+
* trigger. On the web it is a `menu` of `menuitem`s: the arrow keys, Home and
|
|
4816
|
+
* End move between enabled items and Space or Enter picks one. A picked
|
|
4817
|
+
* item's `onPress` runs once the menu has left the screen, so it can open a
|
|
4818
|
+
* `<ConfirmDialog>`. Follows the theme's `popover` scope (Design > Components
|
|
4819
|
+
* > Dropdown menus).
|
|
4820
|
+
*
|
|
4821
|
+
* @example
|
|
4822
|
+
* <Menu
|
|
4823
|
+
* trigger={<IconButton icon="more-horizontal" accessibilityLabel="More actions" />}
|
|
4824
|
+
* accessibilityLabel="Order actions"
|
|
4825
|
+
* items={[
|
|
4826
|
+
* { label: "Edit", icon: "pencil", onPress: edit },
|
|
4827
|
+
* canDelete && { label: "Delete", icon: "trash-2", danger: true, onPress: askDelete },
|
|
4828
|
+
* ]}
|
|
4829
|
+
* />
|
|
4830
|
+
*/
|
|
4831
|
+
export const Menu: (props: {
|
|
4832
|
+
/** ONE pressable element; the menu adds the press that opens it. */
|
|
4833
|
+
trigger: ReactNode;
|
|
4834
|
+
/** Falsy entries are skipped, so `cond && { … }` works. */
|
|
4835
|
+
items: Array<MenuItem | null | false | undefined>;
|
|
4836
|
+
accessibilityLabel?: string;
|
|
4837
|
+
/** Default "bottom"; it flips at the screen edge. */
|
|
4838
|
+
placement?: PopoverPlacement;
|
|
4839
|
+
/** The sheet backdrop's name. Default "Close". */
|
|
4840
|
+
closeAccessibilityLabel?: string;
|
|
4841
|
+
/** On the panel; the item list takes `-items`. */
|
|
4842
|
+
testID?: string;
|
|
4843
|
+
}) => any;
|
|
4844
|
+
|
|
4845
|
+
/**
|
|
4846
|
+
* Free content beside a trigger: quick filters, a swatch picker, a short
|
|
4847
|
+
* detail card. Placed like `<Menu>`, closed the same ways. Components inside
|
|
4848
|
+
* read a theme inked for the panel. Follows the theme's `popover` scope.
|
|
4849
|
+
*
|
|
4850
|
+
* @example
|
|
4851
|
+
* <Popover trigger={<Button variant="secondary" title="Filters" />} accessibilityLabel="Filters">
|
|
4852
|
+
* {({ close }) => <Button title="Apply" onPress={() => { apply(); close(); }} />}
|
|
4853
|
+
* </Popover>
|
|
4854
|
+
*/
|
|
4855
|
+
export const Popover: (props: {
|
|
4856
|
+
/** ONE pressable element; the popover adds the press that opens it. */
|
|
4857
|
+
trigger: ReactNode;
|
|
4858
|
+
children?: ReactNode | ((api: { close: () => void }) => ReactNode);
|
|
4859
|
+
/** Pass with `onVisibleChange` to open and close it from your own code. */
|
|
4860
|
+
visible?: boolean;
|
|
4861
|
+
onVisibleChange?: (visible: boolean) => void;
|
|
4862
|
+
/** Default "bottom"; it flips at the screen edge. */
|
|
4863
|
+
placement?: PopoverPlacement;
|
|
4864
|
+
accessibilityLabel?: string;
|
|
4865
|
+
/** The sheet backdrop's name. Default "Close". */
|
|
4866
|
+
closeAccessibilityLabel?: string;
|
|
4867
|
+
/** On the panel. */
|
|
4868
|
+
testID?: string;
|
|
4869
|
+
}) => any;
|
|
4870
|
+
|
|
4871
|
+
/**
|
|
4872
|
+
* A short label for the one pressable element it wraps, usually an
|
|
4873
|
+
* icon-only button that keeps its own `accessibilityLabel`. On the web it
|
|
4874
|
+
* shows on hover and keyboard focus; a touch screen has no hover, so there a
|
|
4875
|
+
* long press shows it (a bottom sheet on a phone). A child with its own
|
|
4876
|
+
* `onLongPress` keeps it and gets no long-press tooltip. The tooltip wraps
|
|
4877
|
+
* the child in a `View`. Follows the theme's `popover` scope.
|
|
4878
|
+
*
|
|
4879
|
+
* @example
|
|
4880
|
+
* <Tooltip label="Delete">
|
|
4881
|
+
* <IconButton icon="trash-2" accessibilityLabel="Delete" onPress={remove} />
|
|
4882
|
+
* </Tooltip>
|
|
4883
|
+
*/
|
|
4884
|
+
export const Tooltip: (props: {
|
|
4885
|
+
label: string;
|
|
4886
|
+
/** Default "top"; it flips at the screen edge. */
|
|
4887
|
+
placement?: PopoverPlacement;
|
|
4888
|
+
/** On the label. */
|
|
4889
|
+
testID?: string;
|
|
4890
|
+
children: ReactNode;
|
|
4891
|
+
}) => any;
|
|
4892
|
+
|
|
4432
4893
|
/**
|
|
4433
4894
|
* Themed collapsible sections. The surface comes from the theme's `card`
|
|
4434
4895
|
* scope and the headers and dividers from its `list` scope, so every
|
package/dist/index.js
CHANGED
|
@@ -112,6 +112,8 @@ export {
|
|
|
112
112
|
widthTier,
|
|
113
113
|
WIDE_WIDTH_PX,
|
|
114
114
|
} from "./container-width.js";
|
|
115
|
+
// Balanced lines of cells sized from the grid's own measured width.
|
|
116
|
+
export { Grid } from "./grid.js";
|
|
115
117
|
// REQ-WSDK-PLATFORM §6 — Tier A hooks. Each ships in a per-platform file
|
|
116
118
|
// (./clipboard.js / .native.js, ./toast.js / .native.js); index.js picks
|
|
117
119
|
// the web variant and index.native.js picks the native variant.
|
|
@@ -241,6 +243,8 @@ export { List, ListRow, ListHeader, EmptyState } from "./list.js";
|
|
|
241
243
|
export { Badge, Avatar, Progress, Stat, Divider } from "./detail-parts.js";
|
|
242
244
|
export { initialsFor } from "./initials.js";
|
|
243
245
|
export { avatarColorFor } from "./avatar-color.js";
|
|
246
|
+
// A stored file's picture: a themed placeholder, then a fallback on failure.
|
|
247
|
+
export { FileImage } from "./file-image.js";
|
|
244
248
|
// The one card surface: the theme's `card` scope, a gradient fill, margin.
|
|
245
249
|
export { Card } from "./card.js";
|
|
246
250
|
export {
|
|
@@ -258,7 +262,7 @@ export {
|
|
|
258
262
|
cardGradientProps,
|
|
259
263
|
} from "./card-style.js";
|
|
260
264
|
// The themed button; follows the theme's button, destructive and ring scopes.
|
|
261
|
-
export { Button, BUTTON_VARIANTS } from "./button.js";
|
|
265
|
+
export { Button, IconButton, BUTTON_VARIANTS } from "./button.js";
|
|
262
266
|
export {
|
|
263
267
|
BUTTON_PADDING_MAX,
|
|
264
268
|
BUTTON_BORDER_WIDTH_MAX,
|
|
@@ -278,6 +282,10 @@ export { Checkbox } from "./checkbox.js";
|
|
|
278
282
|
export { Switch } from "./switch.js";
|
|
279
283
|
export { Select } from "./select.js";
|
|
280
284
|
export { SearchField } from "./search-field.js";
|
|
285
|
+
// A searchable `<Select>` of users, groups or one table's records.
|
|
286
|
+
export { PeoplePicker } from "./people-picker.js";
|
|
287
|
+
// Pick one of a short visible list; `muted` scope, or `tabs` when segmented.
|
|
288
|
+
export { RadioGroup } from "./radio-group.js";
|
|
281
289
|
// Space for a control whose role is not a button; a no-op on native.
|
|
282
290
|
export { spaceActivates } from "./form-control-logic.js";
|
|
283
291
|
// A themed tab strip; follows the theme's `tabs` scope.
|
|
@@ -292,8 +300,13 @@ export { Modal } from "./modal.js";
|
|
|
292
300
|
export { ConfirmDialog } from "./confirm-dialog.js";
|
|
293
301
|
// Themed filter chips, tags and pills; follow the theme's `chip` scope.
|
|
294
302
|
export { Chip, ChipGroup } from "./chip.js";
|
|
303
|
+
// Themed bar, line, area and donut charts; follow the theme's `chart` scope.
|
|
304
|
+
export { Chart } from "./chart.js";
|
|
305
|
+
export { chartColors } from "./chart-tokens.js";
|
|
295
306
|
// A themed file chooser on `<FilePicker>`; follows the theme's `muted` scope.
|
|
296
307
|
export { FileUpload } from "./file-upload.js";
|
|
308
|
+
// Anchored actions, content and labels; follow the theme's `popover` scope.
|
|
309
|
+
export { Menu, Popover, Tooltip } from "./popover.js";
|
|
297
310
|
// The semantic text tiers, shared with the built-in widgets.
|
|
298
311
|
export {
|
|
299
312
|
textRoleStyle,
|