@twentyfirstmedia/elements 0.2.1 → 0.3.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.
@@ -148,6 +148,18 @@ export interface UIProviderProps {
148
148
  * reduced-motion setting always turns motion off.
149
149
  */
150
150
  motion?: Motion;
151
+ /**
152
+ * BCP 47 locale for the numbers, money, percentages and dates components show (`"de-DE"`).
153
+ * Default `"en-US"`; a nested provider keeps its parent's locale unless it sets its own.
154
+ */
155
+ locale?: string;
156
+ /**
157
+ * Your own text for any built-in string: accessible names, button texts, placeholders, status
158
+ * words (`{ close: "Schließen", selectedCount: (n) => \`${n} ausgewählt\` }`). Partial: what you
159
+ * leave out stays English (or what an outer provider set). Props such as `title` or `label` on a
160
+ * component still win. See `DEFAULT_STRINGS` for every key.
161
+ */
162
+ messages?: UIMessages;
151
163
  className?: string;
152
164
  style?: CSSProperties;
153
165
  children?: ReactNode;
@@ -165,23 +177,51 @@ export interface BaseProps {
165
177
 
166
178
  export type Tint = "sky" | "mint" | "lilac" | "butter" | "blush";
167
179
 
168
- export interface ButtonProps extends BaseProps {
180
+ /**
181
+ * Native attributes `Button` and `IconButton` pass to their `<button>` (or, with `asChild`, to the
182
+ * child). Every other attribute of `<button>` (`data-*`, events such as `onKeyDown`, `ref` in
183
+ * React 19) is passed on as well; these are the ones worth knowing.
184
+ */
185
+ export interface NativeButtonProps {
186
+ id?: string;
187
+ /** Form field name and value, sent with the form when this button submits it. */
188
+ name?: string;
189
+ value?: string;
190
+ /** The id of the form this button belongs to, when it sits outside it. */
191
+ form?: string;
192
+ title?: string;
193
+ tabIndex?: number;
194
+ autoFocus?: boolean;
195
+ "aria-label"?: string;
196
+ "aria-labelledby"?: string;
197
+ "aria-describedby"?: string;
198
+ /** For disclosure and menu triggers: whether what the button controls is open. */
199
+ "aria-expanded"?: boolean | "true" | "false";
200
+ "aria-controls"?: string;
201
+ "aria-haspopup"?: boolean | "true" | "false" | "menu" | "listbox" | "tree" | "grid" | "dialog";
202
+ /** For toggle buttons. */
203
+ "aria-pressed"?: boolean | "true" | "false" | "mixed";
204
+ "aria-current"?: boolean | "true" | "false" | "page" | "step" | "location" | "date" | "time";
205
+ }
206
+ export interface ButtonProps extends BaseProps, NativeButtonProps {
169
207
  variant?: "primary" | "secondary" | "soft" | "ghost" | "danger" | "danger-solid";
170
208
  size?: "md" | "sm";
171
209
  icon?: IconName;
172
210
  iconRight?: IconName;
173
211
  disabled?: boolean;
174
- type?: "button" | "submit";
212
+ type?: "button" | "submit" | "reset";
175
213
  onClick?: (e: MouseEvent<HTMLButtonElement>) => void;
176
214
  children?: ReactNode;
177
215
  /** Render the single child element (a link, a router Link) with the button's look instead of a <button>. */
178
216
  asChild?: boolean;
179
217
  }
180
- export interface IconButtonProps extends BaseProps {
218
+ export interface IconButtonProps extends BaseProps, NativeButtonProps {
181
219
  icon: IconName;
220
+ /** Accessible name and tooltip (`aria-label` and `title`); `aria-label` or `title` override them. */
182
221
  label: string;
183
222
  variant?: "soft" | "solid" | "outline" | "ghost";
184
223
  size?: "sm" | "md" | "lg";
224
+ type?: "button" | "submit" | "reset";
185
225
  onClick?: (e: MouseEvent<HTMLButtonElement>) => void;
186
226
  disabled?: boolean;
187
227
  /** Render the single child element (a link) with the button's look; the icon is placed inside it. */
@@ -251,6 +291,8 @@ export interface TextareaProps extends FieldProps, BaseProps {
251
291
  }
252
292
  export interface SearchFieldProps extends BaseProps {
253
293
  placeholder?: string;
294
+ /** Accessible name (default: the placeholder, or "Search"). */
295
+ label?: string;
254
296
  shortcut?: string;
255
297
  value?: string;
256
298
  onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
@@ -442,8 +484,17 @@ export interface BreadcrumbProps extends BaseProps {
442
484
  items: string[];
443
485
  }
444
486
  export interface PaginationProps extends BaseProps {
487
+ /** Number of pages. */
445
488
  total: number;
489
+ /**
490
+ * The current page (1-based). Controlled together with `onChange`; without `onChange` it is
491
+ * only the start page, as in earlier versions (prefer `defaultPage` for that).
492
+ */
446
493
  page?: number;
494
+ /** Start page when uncontrolled (default 1). */
495
+ defaultPage?: number;
496
+ /** A page was picked (previous, next or a number); receives the new 1-based page. */
497
+ onChange?: (page: number) => void;
447
498
  }
448
499
  export interface AppShellProps extends BaseProps {
449
500
  active?: string;
@@ -751,6 +802,7 @@ export interface FormFieldProps extends BaseProps {
751
802
  children?: ReactNode;
752
803
  }
753
804
  export interface TextFieldProps extends Omit<FormFieldProps, "children"> {
805
+ /** Input type (`"text"` by default): `"email"`, `"number"`, `"tel"`, `"url"`, `"password"` … */
754
806
  type?: string;
755
807
  icon?: IconName;
756
808
  suffix?: ReactNode;
@@ -758,7 +810,23 @@ export interface TextFieldProps extends Omit<FormFieldProps, "children"> {
758
810
  defaultValue?: string;
759
811
  placeholder?: string;
760
812
  disabled?: boolean;
813
+ readOnly?: boolean;
761
814
  autoComplete?: string;
815
+ autoFocus?: boolean;
816
+ /** Smallest value for `type="number"`, `"date"` and the like (native `min`). */
817
+ min?: number | string;
818
+ /** Largest value (native `max`). */
819
+ max?: number | string;
820
+ /** Step between valid values (native `step`), e.g. `1` for whole numbers or `"any"`. */
821
+ step?: number | string;
822
+ /** Fewest characters (native `minlength`). */
823
+ minLength?: number;
824
+ /** Most characters (native `maxlength`). */
825
+ maxLength?: number;
826
+ /** Pattern the value must match (native `pattern`). */
827
+ pattern?: string;
828
+ /** Virtual keyboard on touch devices (native `inputmode`), e.g. `"numeric"` or `"decimal"`. */
829
+ inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search";
762
830
  onChange?: (e: ChangeEvent<HTMLInputElement>) => void;
763
831
  onBlur?: (e: ChangeEvent<HTMLInputElement>) => void;
764
832
  }
@@ -864,13 +932,34 @@ export interface UploadFile {
864
932
  id: string;
865
933
  name: string;
866
934
  size: number;
935
+ /** Upload progress 0–100: a bar while below 100, "uploaded" at 100. */
867
936
  progress: number;
937
+ /** The picked or dropped file (set by FileDrop for files it adds). */
938
+ file?: File;
868
939
  }
869
940
  export interface FileDropProps extends BaseProps {
941
+ /** The listed files (controlled); set `progress` per file to show real upload progress. */
870
942
  files?: UploadFile[];
943
+ /** The list changed: files added (with their `file`) or removed. */
871
944
  onChange?: (f: UploadFile[]) => void;
945
+ /**
946
+ * The person picked or dropped files: the real `File` objects, after `accept` and `multiple`.
947
+ * Upload them yourself. To show progress, control `files` and set each `progress`; an
948
+ * uncontrolled list shows them with their size only.
949
+ */
950
+ onFiles?: (files: File[]) => void;
951
+ /** Dropped files that do not match `accept` (show an inline Alert). */
952
+ onReject?: (files: File[]) => void;
953
+ /** A listed file was removed or its upload cancelled. */
954
+ onRemove?: (f: UploadFile) => void;
955
+ /**
956
+ * Animate made-up progress for added files, as a demo of the look. Default: on without
957
+ * `onFiles` (as before), off with it.
958
+ */
959
+ simulateProgress?: boolean;
872
960
  title?: string;
873
961
  hint?: string;
962
+ /** Accepted types, as for `<input type="file">` ("image/*,.pdf"); also checked on drop. */
874
963
  accept?: string;
875
964
  multiple?: boolean;
876
965
  }
@@ -1258,6 +1347,8 @@ export interface PlanCardProps extends BaseProps {
1258
1347
  flag?: string;
1259
1348
  current?: boolean;
1260
1349
  cta?: string;
1350
+ /** Disable the button, e.g. while a checkout starts or when the plan cannot be picked. */
1351
+ disabled?: boolean;
1261
1352
  onPick?: () => void;
1262
1353
  }
1263
1354
 
@@ -2252,6 +2343,17 @@ export interface ImageVariantsProps extends BaseProps {
2252
2343
  tint?: Tint;
2253
2344
  actions?: ReactNode;
2254
2345
  }
2346
+ /** `referrerPolicy` values of `<img>`. */
2347
+ export type ImageReferrerPolicy =
2348
+ | ""
2349
+ | "no-referrer"
2350
+ | "no-referrer-when-downgrade"
2351
+ | "origin"
2352
+ | "origin-when-cross-origin"
2353
+ | "same-origin"
2354
+ | "strict-origin"
2355
+ | "strict-origin-when-cross-origin"
2356
+ | "unsafe-url";
2255
2357
  export interface GalleryItem {
2256
2358
  src?: string;
2257
2359
  alt?: string;
@@ -2261,6 +2363,13 @@ export interface GalleryItem {
2261
2363
  }
2262
2364
  export interface GalleryProps extends BaseProps {
2263
2365
  items: GalleryItem[];
2366
+ /**
2367
+ * Loading of the main image: `"lazy"` (default) waits until the gallery is near the viewport;
2368
+ * use `"eager"` for a gallery at the top of the page. Thumbnails always load lazily.
2369
+ */
2370
+ loading?: "lazy" | "eager";
2371
+ /** `referrerPolicy` of every image, e.g. `"no-referrer"` for photos from other hosts. */
2372
+ referrerPolicy?: ImageReferrerPolicy;
2264
2373
  start?: number;
2265
2374
  ratio?: string;
2266
2375
  thumbs?: boolean;
@@ -2280,6 +2389,17 @@ export interface BeforeAfterProps extends BaseProps {
2280
2389
  ratio?: string;
2281
2390
  beforeLabel?: string;
2282
2391
  afterLabel?: string;
2392
+ /** Accessible name of the slider (default "Compare before and after"). */
2393
+ label?: string;
2394
+ /**
2395
+ * What screen readers hear for a position (0–100, the share of "before"). Default:
2396
+ * "Before 40%, After 60%", with your `beforeLabel`/`afterLabel`.
2397
+ */
2398
+ valueText?: (percent: number) => string;
2399
+ /** Loading of both images (default `"lazy"`). */
2400
+ loading?: "lazy" | "eager";
2401
+ /** `referrerPolicy` of both images. */
2402
+ referrerPolicy?: ImageReferrerPolicy;
2283
2403
  }
2284
2404
 
2285
2405
  /* ── Kit 5: real estate ── */
@@ -2906,7 +3026,7 @@ export type TfNumberInputElement = TfElement<NumberInputProps>;
2906
3026
  export type TfSliderElement = TfElement<SliderProps>;
2907
3027
  /** `<tf-otp-input>`: The OtpInput component as a custom element. */
2908
3028
  export type TfOtpInputElement = TfElement<OtpInputProps>;
2909
- /** `<tf-file-drop>`: Dashed drop zone plus an upload list with progress. */
3029
+ /** `<tf-file-drop>`: Dashed drop zone plus an upload list. */
2910
3030
  export type TfFileDropElement = TfElement<FileDropProps>;
2911
3031
  /** `<tf-button>`: The Button component as a custom element. */
2912
3032
  export type TfButtonElement = TfElement<ButtonProps>;