@dragunio/fe-libs 0.1.11 → 0.1.13

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/dist/index.d.mts CHANGED
@@ -411,7 +411,21 @@ type SelectionProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'default
411
411
  disabled?: boolean;
412
412
  name?: string;
413
413
  onKeyDown?: KeyboardEventHandler<HTMLButtonElement>;
414
+ /**
415
+ * Caps the field width. Numbers are pixels (`240` → `240px`); strings are
416
+ * any CSS length (`'16rem'`, `'50%'`). The field still shrinks inside
417
+ * narrower containers.
418
+ */
419
+ maxWidth?: number | string;
420
+ /**
421
+ * How a selected label longer than the field is shown:
422
+ * - `'ellipsis'` (default): one line ending in `…`; the full text appears
423
+ * in a tooltip on hover or focus.
424
+ * - `'wrap'`: the label wraps onto more lines and the field grows taller.
425
+ */
426
+ overflow?: SelectionOverflow;
414
427
  };
428
+ type SelectionOverflow = 'ellipsis' | 'wrap';
415
429
 
416
430
  /** A rounded, searchable custom dropdown with single, multiple, and tag modes. */
417
431
  declare const Selection: react.ForwardRefExoticComponent<Omit<react.HTMLAttributes<HTMLDivElement>, "value" | "defaultValue" | "onChange" | "onKeyDown"> & {
@@ -435,6 +449,8 @@ declare const Selection: react.ForwardRefExoticComponent<Omit<react.HTMLAttribut
435
449
  disabled?: boolean;
436
450
  name?: string;
437
451
  onKeyDown?: react.KeyboardEventHandler<HTMLButtonElement>;
452
+ maxWidth?: number | string;
453
+ overflow?: SelectionOverflow;
438
454
  } & react.RefAttributes<HTMLDivElement>>;
439
455
 
440
456
  declare function formatNumber(value: number, decimals?: number, thousandSeparator?: string, decimalSeparator?: string): string;
@@ -510,11 +526,26 @@ type CurrencyInputProps = Omit<NumberInputProps, 'suffix' | 'endAdornment'> & {
510
526
  declare function CurrencyInput({ suffix, currencies, currency, defaultCurrency, onCurrencyChange, className, disabled, ...props }: CurrencyInputProps): react.JSX.Element;
511
527
 
512
528
  type DateRange = [Date | null, Date | null];
529
+ /** Text of the picker. `weekdays` runs from Monday to Sunday. */
530
+ type DateTimePickerLabels = {
531
+ weekdays: readonly [string, string, string, string, string, string, string];
532
+ today: string;
533
+ time: string;
534
+ start: string;
535
+ end: string;
536
+ previousMonth: string;
537
+ nextMonth: string;
538
+ dialog: string;
539
+ selectDateTime: string;
540
+ selectDateRange: string;
541
+ };
513
542
  type DateTimeBaseProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> & FieldBaseProps & {
514
543
  format?: string;
515
544
  disabled?: boolean;
516
545
  placeholder?: string;
517
546
  locale?: string;
547
+ /** Overrides the text chosen from `locale` (Vietnamese for `vi*`, otherwise English). */
548
+ labels?: Partial<DateTimePickerLabels>;
518
549
  };
519
550
  type DateTimePickerSingleProps = DateTimeBaseProps & {
520
551
  mode?: 'single';
@@ -1001,4 +1032,4 @@ declare function NotFoundLost(props: NotFoundSceneProps): react.JSX.Element;
1001
1032
  /** A 404 page with a stable random design, or an explicitly selected variant. */
1002
1033
  declare function NotFound({ variant, ...props }: NotFoundProps): react.JSX.Element;
1003
1034
 
1004
- export { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarShape, type AvatarSize, Button, ButtonBar, type ButtonBarAction, type ButtonBarItem, type ButtonBarProps, type ButtonColor, type ButtonHierarchy, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, Chip, type ChipProps, type ChipStatus, type ChipVariant, type ColumnResizeHandler, type ControlLabelPosition, type Currency, CurrencyInput, type CurrencyInputProps, type DateRange, DateTimePicker, type DateTimePickerProps, type DateTimePickerRangeProps, type DateTimePickerSingleProps, type DescriptionDisplay, Drawer, type DrawerProps, type DrawerSide, type DrawerWidth, type DrawerWidthPreset, DrawerWidths, EmailInput, type EmailInputProps, ExpandableSection, type ExpandableSectionProps, FILE_UPLOAD_ACCEPTS, type FieldError, FilePreview, type FilePreviewActionHandler, type FilePreviewCloseReason, type FilePreviewKind, type FilePreviewProps, FileUpload, type FileUploadAccept, type FileUploadFileType, type FileUploadProps, type FileUploadRejection, type FileUploadRejectionCode, type InputValidator, Loading, type LoadingProps, type LoadingSize, Message, type MessageOptions, type MessageProps, type MessageSeverity, Modal, type ModalAction, type ModalProps, type ModalSize, NotFound, NotFoundCaveman, NotFoundLost, type NotFoundProps, type NotFoundSceneProps, type NotFoundVariant, NotFoundYeti, NumberInput, type NumberInputProps, Pagination, type PaginationProps, PasswordInput, type PasswordInputProps, PhoneNumberInput, type PhoneNumberInputProps, ProgressBar, type ProgressBarProps, type ProgressBarSize, RadioButton, type RadioButtonProps, RadioGroup, type RadioGroupOption, type RadioGroupProps, type RadioValue, Selection, type SelectionOption, type SelectionProps, type SelectionValue, Skeleton, SkeletonBox, type SkeletonBoxProps, SkeletonCircle, SkeletonLine, type SkeletonProps, type SkeletonSizeProps, SkeletonSquare, type SkeletonVariant, Snackbar, type SnackbarAnchorOrigin, type SnackbarProps, type TabChangeEvent, type TabItem, Table, TableBody, TableCaption, TableCell, type TableCellProps, type TableColumn, type TableColumnWidths, type TableData, TableHead, TableHeader, type TableHeaderProps, type TablePaginationPosition, type TableProps, type TableResizeHandler, TableRow, Tabs, type TabsProps, type TabsScrollButtons, type TabsVariant, TextArea, type TextAreaProps, TextInput, type TextInputProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, type ValidatedTextInputProps, type ValidationTiming, formatFileSize, formatNumber, getFilePreviewKind, getIconSize, message, normalizePhoneNumber, validateEmail, validatePassword, validatePhoneNumber };
1035
+ export { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarShape, type AvatarSize, Button, ButtonBar, type ButtonBarAction, type ButtonBarItem, type ButtonBarProps, type ButtonColor, type ButtonHierarchy, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, Chip, type ChipProps, type ChipStatus, type ChipVariant, type ColumnResizeHandler, type ControlLabelPosition, type Currency, CurrencyInput, type CurrencyInputProps, type DateRange, DateTimePicker, type DateTimePickerLabels, type DateTimePickerProps, type DateTimePickerRangeProps, type DateTimePickerSingleProps, type DescriptionDisplay, Drawer, type DrawerProps, type DrawerSide, type DrawerWidth, type DrawerWidthPreset, DrawerWidths, EmailInput, type EmailInputProps, ExpandableSection, type ExpandableSectionProps, FILE_UPLOAD_ACCEPTS, type FieldError, FilePreview, type FilePreviewActionHandler, type FilePreviewCloseReason, type FilePreviewKind, type FilePreviewProps, FileUpload, type FileUploadAccept, type FileUploadFileType, type FileUploadProps, type FileUploadRejection, type FileUploadRejectionCode, type InputValidator, Loading, type LoadingProps, type LoadingSize, Message, type MessageOptions, type MessageProps, type MessageSeverity, Modal, type ModalAction, type ModalProps, type ModalSize, NotFound, NotFoundCaveman, NotFoundLost, type NotFoundProps, type NotFoundSceneProps, type NotFoundVariant, NotFoundYeti, NumberInput, type NumberInputProps, Pagination, type PaginationProps, PasswordInput, type PasswordInputProps, PhoneNumberInput, type PhoneNumberInputProps, ProgressBar, type ProgressBarProps, type ProgressBarSize, RadioButton, type RadioButtonProps, RadioGroup, type RadioGroupOption, type RadioGroupProps, type RadioValue, Selection, type SelectionOption, type SelectionOverflow, type SelectionProps, type SelectionValue, Skeleton, SkeletonBox, type SkeletonBoxProps, SkeletonCircle, SkeletonLine, type SkeletonProps, type SkeletonSizeProps, SkeletonSquare, type SkeletonVariant, Snackbar, type SnackbarAnchorOrigin, type SnackbarProps, type TabChangeEvent, type TabItem, Table, TableBody, TableCaption, TableCell, type TableCellProps, type TableColumn, type TableColumnWidths, type TableData, TableHead, TableHeader, type TableHeaderProps, type TablePaginationPosition, type TableProps, type TableResizeHandler, TableRow, Tabs, type TabsProps, type TabsScrollButtons, type TabsVariant, TextArea, type TextAreaProps, TextInput, type TextInputProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, type ValidatedTextInputProps, type ValidationTiming, formatFileSize, formatNumber, getFilePreviewKind, getIconSize, message, normalizePhoneNumber, validateEmail, validatePassword, validatePhoneNumber };
package/dist/index.d.ts CHANGED
@@ -411,7 +411,21 @@ type SelectionProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'default
411
411
  disabled?: boolean;
412
412
  name?: string;
413
413
  onKeyDown?: KeyboardEventHandler<HTMLButtonElement>;
414
+ /**
415
+ * Caps the field width. Numbers are pixels (`240` → `240px`); strings are
416
+ * any CSS length (`'16rem'`, `'50%'`). The field still shrinks inside
417
+ * narrower containers.
418
+ */
419
+ maxWidth?: number | string;
420
+ /**
421
+ * How a selected label longer than the field is shown:
422
+ * - `'ellipsis'` (default): one line ending in `…`; the full text appears
423
+ * in a tooltip on hover or focus.
424
+ * - `'wrap'`: the label wraps onto more lines and the field grows taller.
425
+ */
426
+ overflow?: SelectionOverflow;
414
427
  };
428
+ type SelectionOverflow = 'ellipsis' | 'wrap';
415
429
 
416
430
  /** A rounded, searchable custom dropdown with single, multiple, and tag modes. */
417
431
  declare const Selection: react.ForwardRefExoticComponent<Omit<react.HTMLAttributes<HTMLDivElement>, "value" | "defaultValue" | "onChange" | "onKeyDown"> & {
@@ -435,6 +449,8 @@ declare const Selection: react.ForwardRefExoticComponent<Omit<react.HTMLAttribut
435
449
  disabled?: boolean;
436
450
  name?: string;
437
451
  onKeyDown?: react.KeyboardEventHandler<HTMLButtonElement>;
452
+ maxWidth?: number | string;
453
+ overflow?: SelectionOverflow;
438
454
  } & react.RefAttributes<HTMLDivElement>>;
439
455
 
440
456
  declare function formatNumber(value: number, decimals?: number, thousandSeparator?: string, decimalSeparator?: string): string;
@@ -510,11 +526,26 @@ type CurrencyInputProps = Omit<NumberInputProps, 'suffix' | 'endAdornment'> & {
510
526
  declare function CurrencyInput({ suffix, currencies, currency, defaultCurrency, onCurrencyChange, className, disabled, ...props }: CurrencyInputProps): react.JSX.Element;
511
527
 
512
528
  type DateRange = [Date | null, Date | null];
529
+ /** Text of the picker. `weekdays` runs from Monday to Sunday. */
530
+ type DateTimePickerLabels = {
531
+ weekdays: readonly [string, string, string, string, string, string, string];
532
+ today: string;
533
+ time: string;
534
+ start: string;
535
+ end: string;
536
+ previousMonth: string;
537
+ nextMonth: string;
538
+ dialog: string;
539
+ selectDateTime: string;
540
+ selectDateRange: string;
541
+ };
513
542
  type DateTimeBaseProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> & FieldBaseProps & {
514
543
  format?: string;
515
544
  disabled?: boolean;
516
545
  placeholder?: string;
517
546
  locale?: string;
547
+ /** Overrides the text chosen from `locale` (Vietnamese for `vi*`, otherwise English). */
548
+ labels?: Partial<DateTimePickerLabels>;
518
549
  };
519
550
  type DateTimePickerSingleProps = DateTimeBaseProps & {
520
551
  mode?: 'single';
@@ -1001,4 +1032,4 @@ declare function NotFoundLost(props: NotFoundSceneProps): react.JSX.Element;
1001
1032
  /** A 404 page with a stable random design, or an explicitly selected variant. */
1002
1033
  declare function NotFound({ variant, ...props }: NotFoundProps): react.JSX.Element;
1003
1034
 
1004
- export { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarShape, type AvatarSize, Button, ButtonBar, type ButtonBarAction, type ButtonBarItem, type ButtonBarProps, type ButtonColor, type ButtonHierarchy, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, Chip, type ChipProps, type ChipStatus, type ChipVariant, type ColumnResizeHandler, type ControlLabelPosition, type Currency, CurrencyInput, type CurrencyInputProps, type DateRange, DateTimePicker, type DateTimePickerProps, type DateTimePickerRangeProps, type DateTimePickerSingleProps, type DescriptionDisplay, Drawer, type DrawerProps, type DrawerSide, type DrawerWidth, type DrawerWidthPreset, DrawerWidths, EmailInput, type EmailInputProps, ExpandableSection, type ExpandableSectionProps, FILE_UPLOAD_ACCEPTS, type FieldError, FilePreview, type FilePreviewActionHandler, type FilePreviewCloseReason, type FilePreviewKind, type FilePreviewProps, FileUpload, type FileUploadAccept, type FileUploadFileType, type FileUploadProps, type FileUploadRejection, type FileUploadRejectionCode, type InputValidator, Loading, type LoadingProps, type LoadingSize, Message, type MessageOptions, type MessageProps, type MessageSeverity, Modal, type ModalAction, type ModalProps, type ModalSize, NotFound, NotFoundCaveman, NotFoundLost, type NotFoundProps, type NotFoundSceneProps, type NotFoundVariant, NotFoundYeti, NumberInput, type NumberInputProps, Pagination, type PaginationProps, PasswordInput, type PasswordInputProps, PhoneNumberInput, type PhoneNumberInputProps, ProgressBar, type ProgressBarProps, type ProgressBarSize, RadioButton, type RadioButtonProps, RadioGroup, type RadioGroupOption, type RadioGroupProps, type RadioValue, Selection, type SelectionOption, type SelectionProps, type SelectionValue, Skeleton, SkeletonBox, type SkeletonBoxProps, SkeletonCircle, SkeletonLine, type SkeletonProps, type SkeletonSizeProps, SkeletonSquare, type SkeletonVariant, Snackbar, type SnackbarAnchorOrigin, type SnackbarProps, type TabChangeEvent, type TabItem, Table, TableBody, TableCaption, TableCell, type TableCellProps, type TableColumn, type TableColumnWidths, type TableData, TableHead, TableHeader, type TableHeaderProps, type TablePaginationPosition, type TableProps, type TableResizeHandler, TableRow, Tabs, type TabsProps, type TabsScrollButtons, type TabsVariant, TextArea, type TextAreaProps, TextInput, type TextInputProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, type ValidatedTextInputProps, type ValidationTiming, formatFileSize, formatNumber, getFilePreviewKind, getIconSize, message, normalizePhoneNumber, validateEmail, validatePassword, validatePhoneNumber };
1035
+ export { Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarShape, type AvatarSize, Button, ButtonBar, type ButtonBarAction, type ButtonBarItem, type ButtonBarProps, type ButtonColor, type ButtonHierarchy, type ButtonProps, type ButtonSize, type ButtonVariant, Checkbox, type CheckboxProps, Chip, type ChipProps, type ChipStatus, type ChipVariant, type ColumnResizeHandler, type ControlLabelPosition, type Currency, CurrencyInput, type CurrencyInputProps, type DateRange, DateTimePicker, type DateTimePickerLabels, type DateTimePickerProps, type DateTimePickerRangeProps, type DateTimePickerSingleProps, type DescriptionDisplay, Drawer, type DrawerProps, type DrawerSide, type DrawerWidth, type DrawerWidthPreset, DrawerWidths, EmailInput, type EmailInputProps, ExpandableSection, type ExpandableSectionProps, FILE_UPLOAD_ACCEPTS, type FieldError, FilePreview, type FilePreviewActionHandler, type FilePreviewCloseReason, type FilePreviewKind, type FilePreviewProps, FileUpload, type FileUploadAccept, type FileUploadFileType, type FileUploadProps, type FileUploadRejection, type FileUploadRejectionCode, type InputValidator, Loading, type LoadingProps, type LoadingSize, Message, type MessageOptions, type MessageProps, type MessageSeverity, Modal, type ModalAction, type ModalProps, type ModalSize, NotFound, NotFoundCaveman, NotFoundLost, type NotFoundProps, type NotFoundSceneProps, type NotFoundVariant, NotFoundYeti, NumberInput, type NumberInputProps, Pagination, type PaginationProps, PasswordInput, type PasswordInputProps, PhoneNumberInput, type PhoneNumberInputProps, ProgressBar, type ProgressBarProps, type ProgressBarSize, RadioButton, type RadioButtonProps, RadioGroup, type RadioGroupOption, type RadioGroupProps, type RadioValue, Selection, type SelectionOption, type SelectionOverflow, type SelectionProps, type SelectionValue, Skeleton, SkeletonBox, type SkeletonBoxProps, SkeletonCircle, SkeletonLine, type SkeletonProps, type SkeletonSizeProps, SkeletonSquare, type SkeletonVariant, Snackbar, type SnackbarAnchorOrigin, type SnackbarProps, type TabChangeEvent, type TabItem, Table, TableBody, TableCaption, TableCell, type TableCellProps, type TableColumn, type TableColumnWidths, type TableData, TableHead, TableHeader, type TableHeaderProps, type TablePaginationPosition, type TableProps, type TableResizeHandler, TableRow, Tabs, type TabsProps, type TabsScrollButtons, type TabsVariant, TextArea, type TextAreaProps, TextInput, type TextInputProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, type ValidatedTextInputProps, type ValidationTiming, formatFileSize, formatNumber, getFilePreviewKind, getIconSize, message, normalizePhoneNumber, validateEmail, validatePassword, validatePhoneNumber };
package/dist/index.js CHANGED
@@ -2127,6 +2127,9 @@ var Selection = (0, import_react17.forwardRef)(
2127
2127
  disabled = false,
2128
2128
  name,
2129
2129
  onKeyDown,
2130
+ maxWidth,
2131
+ overflow = "ellipsis",
2132
+ style,
2130
2133
  "aria-label": ariaLabel,
2131
2134
  "aria-describedby": ariaDescribedBy,
2132
2135
  "aria-labelledby": ariaLabelledBy,
@@ -2137,6 +2140,7 @@ var Selection = (0, import_react17.forwardRef)(
2137
2140
  const listboxId = triggerId + "-listbox";
2138
2141
  const labelId = generatedId + "-label";
2139
2142
  const messageId2 = generatedId + "-message";
2143
+ const tooltipId = generatedId + "-tooltip";
2140
2144
  const fieldError = getFieldError(error, errorMessage);
2141
2145
  const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
2142
2146
  const resolvedDescription = description ?? helperText;
@@ -2163,6 +2167,26 @@ var Selection = (0, import_react17.forwardRef)(
2163
2167
  const [activeIndex, setActiveIndex] = (0, import_react17.useState)(0);
2164
2168
  const rootRef = (0, import_react17.useRef)(null);
2165
2169
  const menuRef = (0, import_react17.useRef)(null);
2170
+ const valueRef = (0, import_react17.useRef)(null);
2171
+ const [truncated, setTruncated] = (0, import_react17.useState)(false);
2172
+ const [hovered, setHovered] = (0, import_react17.useState)(false);
2173
+ const [focused, setFocused] = (0, import_react17.useState)(false);
2174
+ const showsTags = tag && multiple && selectedOptions.length > 0;
2175
+ const canTruncate = overflow === "ellipsis" && !showsTags && selectedOptions.length > 0;
2176
+ const selectedKey = selectedOptions.map((option) => String(option.value)).join("|");
2177
+ (0, import_react17.useLayoutEffect)(() => {
2178
+ const node = valueRef.current;
2179
+ if (!canTruncate || !node) {
2180
+ setTruncated(false);
2181
+ return;
2182
+ }
2183
+ const measure = () => setTruncated(node.scrollWidth > node.clientWidth + 1);
2184
+ measure();
2185
+ if (typeof ResizeObserver === "undefined") return;
2186
+ const observer = new ResizeObserver(measure);
2187
+ observer.observe(node);
2188
+ return () => observer.disconnect();
2189
+ }, [canTruncate, selectedKey]);
2166
2190
  const [menuPosition, setMenuPosition] = (0, import_react17.useState)(null);
2167
2191
  (0, import_react17.useEffect)(() => {
2168
2192
  const close = (event) => {
@@ -2227,6 +2251,12 @@ var Selection = (0, import_react17.forwardRef)(
2227
2251
  setQuery("");
2228
2252
  };
2229
2253
  const displayLabel = selectedOptions.length ? selectedOptions.map((option) => option.label) : null;
2254
+ const showTooltip = truncated && (hovered || focused) && !open;
2255
+ const renderLabels = () => displayLabel?.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { children: [
2256
+ item,
2257
+ index < displayLabel.length - 1 ? ", " : ""
2258
+ ] }, index));
2259
+ const toPx = (length) => typeof length === "number" ? length + "px" : length;
2230
2260
  const onTriggerKeyDown = (event) => {
2231
2261
  onKeyDown?.(event);
2232
2262
  if (disabled) return;
@@ -2258,12 +2288,14 @@ var Selection = (0, import_react17.forwardRef)(
2258
2288
  className: [
2259
2289
  "fe-selection",
2260
2290
  "fe-selection--" + size,
2291
+ "fe-selection--" + overflow,
2261
2292
  open && "fe-selection--open",
2262
2293
  clearable && selectedOptions.length > 0 && "fe-selection--clearable",
2263
2294
  hasError && "fe-selection--error",
2264
2295
  disabled && "fe-selection--disabled",
2265
2296
  className
2266
2297
  ].filter(Boolean).join(" "),
2298
+ style: maxWidth === void 0 ? style : { ...style, maxWidth: toPx(maxWidth) },
2267
2299
  ...props,
2268
2300
  children: [
2269
2301
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
@@ -2297,16 +2329,24 @@ var Selection = (0, import_react17.forwardRef)(
2297
2329
  "aria-invalid": hasError || void 0,
2298
2330
  "aria-required": isRequired || void 0,
2299
2331
  "aria-labelledby": labelledBy,
2300
- "aria-describedby": describedBy,
2332
+ "aria-describedby": getDescribedBy(
2333
+ describedBy,
2334
+ showTooltip ? tooltipId : void 0
2335
+ ),
2301
2336
  "aria-haspopup": "listbox",
2302
2337
  "aria-expanded": open,
2303
2338
  "aria-controls": listboxId,
2304
2339
  onClick: () => setOpen((current) => !current),
2305
2340
  onKeyDown: onTriggerKeyDown,
2341
+ onMouseEnter: () => setHovered(true),
2342
+ onMouseLeave: () => setHovered(false),
2343
+ onFocus: () => setFocused(true),
2344
+ onBlur: () => setFocused(false),
2306
2345
  children: [
2307
2346
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2308
2347
  "span",
2309
2348
  {
2349
+ ref: valueRef,
2310
2350
  className: [
2311
2351
  "fe-selection__value",
2312
2352
  !selectedOptions.length && "is-placeholder",
@@ -2322,10 +2362,7 @@ var Selection = (0, import_react17.forwardRef)(
2322
2362
  ]
2323
2363
  },
2324
2364
  String(option.value)
2325
- )) : displayLabel.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { children: [
2326
- item,
2327
- index < displayLabel.length - 1 ? ", " : ""
2328
- ] }, index)) : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
2365
+ )) : renderLabels() : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
2329
2366
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: placeholder }),
2330
2367
  isRequired && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fe-field__required", "aria-hidden": "true", children: "*" })
2331
2368
  ] })
@@ -2344,6 +2381,7 @@ var Selection = (0, import_react17.forwardRef)(
2344
2381
  onClick: clear
2345
2382
  }
2346
2383
  ),
2384
+ showTooltip && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { id: tooltipId, role: "tooltip", className: "fe-selection__tooltip", children: renderLabels() }),
2347
2385
  open && menuPosition && (0, import_react_dom2.createPortal)(
2348
2386
  /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
2349
2387
  "div",
@@ -2395,7 +2433,7 @@ var Selection = (0, import_react17.forwardRef)(
2395
2433
  onMouseMove: () => setActiveIndex(index),
2396
2434
  onClick: () => choose(option),
2397
2435
  children: [
2398
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: option.label }),
2436
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fe-selection__option-label", children: option.label }),
2399
2437
  isSelected && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2400
2438
  "span",
2401
2439
  {
@@ -2781,6 +2819,30 @@ function CurrencyInput({
2781
2819
  // packages/form-controls/src/controls/DateTimePicker/date-time-picker.tsx
2782
2820
  var import_react20 = require("react");
2783
2821
  var import_jsx_runtime22 = require("react/jsx-runtime");
2822
+ var LABELS_EN = {
2823
+ weekdays: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
2824
+ today: "Today",
2825
+ time: "Time",
2826
+ start: "Start",
2827
+ end: "End",
2828
+ previousMonth: "Previous month",
2829
+ nextMonth: "Next month",
2830
+ dialog: "Date and time picker",
2831
+ selectDateTime: "Select date and time",
2832
+ selectDateRange: "Select date range"
2833
+ };
2834
+ var LABELS_VI = {
2835
+ weekdays: ["T2", "T3", "T4", "T5", "T6", "T7", "CN"],
2836
+ today: "H\xF4m nay",
2837
+ time: "Gi\u1EDD",
2838
+ start: "B\u1EAFt \u0111\u1EA7u",
2839
+ end: "K\u1EBFt th\xFAc",
2840
+ previousMonth: "Th\xE1ng tr\u01B0\u1EDBc",
2841
+ nextMonth: "Th\xE1ng sau",
2842
+ dialog: "Ch\u1ECDn ng\xE0y v\xE0 gi\u1EDD",
2843
+ selectDateTime: "Ch\u1ECDn ng\xE0y v\xE0 gi\u1EDD",
2844
+ selectDateRange: "Ch\u1ECDn kho\u1EA3ng ng\xE0y"
2845
+ };
2784
2846
  var pad = (value) => String(value).padStart(2, "0");
2785
2847
  function formatDate(date, format) {
2786
2848
  return format.replace(/yyyy/g, String(date.getFullYear())).replace(/MM/g, pad(date.getMonth() + 1)).replace(/dd/g, pad(date.getDate())).replace(/HH/g, pad(date.getHours())).replace(/mm/g, pad(date.getMinutes()));
@@ -2810,12 +2872,17 @@ function DateTimePicker(props) {
2810
2872
  disabled,
2811
2873
  placeholder,
2812
2874
  locale = "en-US",
2875
+ labels,
2813
2876
  className,
2814
2877
  mode = "single",
2815
2878
  id,
2816
2879
  "aria-describedby": ariaDescribedBy,
2817
2880
  "aria-labelledby": ariaLabelledBy
2818
2881
  } = props;
2882
+ const text = {
2883
+ ...locale.toLowerCase().startsWith("vi") ? LABELS_VI : LABELS_EN,
2884
+ ...labels
2885
+ };
2819
2886
  const generatedId = (0, import_react20.useId)();
2820
2887
  const triggerId = id ?? generatedId + "-trigger";
2821
2888
  const labelId = generatedId + "-label";
@@ -2903,6 +2970,15 @@ function DateTimePicker(props) {
2903
2970
  { length: 42 },
2904
2971
  (_, index) => new Date(month.getFullYear(), month.getMonth(), index - offset + 1)
2905
2972
  );
2973
+ const today = /* @__PURE__ */ new Date();
2974
+ const selectToday = () => {
2975
+ setMonth(today);
2976
+ selectDay(today);
2977
+ };
2978
+ const toggleOpen = () => {
2979
+ if (!open) setMonth((isRange ? rangeValue[0] : singleValue) ?? today);
2980
+ setOpen(!open);
2981
+ };
2906
2982
  const selectedForTime = isRange ? editingEnd ? rangeValue[1] : rangeValue[0] : singleValue;
2907
2983
  const setTime = (time) => {
2908
2984
  if (!selectedForTime) return;
@@ -2943,7 +3019,7 @@ function DateTimePicker(props) {
2943
3019
  "aria-labelledby": labelledBy,
2944
3020
  "aria-describedby": describedBy,
2945
3021
  "aria-expanded": open,
2946
- onClick: () => setOpen((current) => !current),
3022
+ onClick: toggleOpen,
2947
3023
  children: [
2948
3024
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { "aria-hidden": "true", children: "\u25F7" }),
2949
3025
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
@@ -2951,7 +3027,7 @@ function DateTimePicker(props) {
2951
3027
  {
2952
3028
  className: !shownValue && placeholder ? "fe-datetime-picker__value is-placeholder" : "fe-datetime-picker__value",
2953
3029
  children: [
2954
- shownValue || placeholder || (isRange ? "Select date range" : "Select date and time"),
3030
+ shownValue || placeholder || (isRange ? text.selectDateRange : text.selectDateTime),
2955
3031
  isRequired && placeholder && !shownValue && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "fe-field__required", "aria-hidden": "true", children: "*" })
2956
3032
  ]
2957
3033
  }
@@ -2964,14 +3040,14 @@ function DateTimePicker(props) {
2964
3040
  {
2965
3041
  className: "fe-datetime-picker__popper",
2966
3042
  role: "dialog",
2967
- "aria-label": "Date and time picker",
3043
+ "aria-label": text.dialog,
2968
3044
  children: [
2969
3045
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "fe-datetime-picker__month", children: [
2970
3046
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2971
3047
  "button",
2972
3048
  {
2973
3049
  type: "button",
2974
- "aria-label": "Previous month",
3050
+ "aria-label": text.previousMonth,
2975
3051
  onClick: () => setMonth(
2976
3052
  (current) => new Date(current.getFullYear(), current.getMonth() - 1, 1)
2977
3053
  ),
@@ -2986,7 +3062,7 @@ function DateTimePicker(props) {
2986
3062
  "button",
2987
3063
  {
2988
3064
  type: "button",
2989
- "aria-label": "Next month",
3065
+ "aria-label": text.nextMonth,
2990
3066
  onClick: () => setMonth(
2991
3067
  (current) => new Date(current.getFullYear(), current.getMonth() + 1, 1)
2992
3068
  ),
@@ -2994,17 +3070,20 @@ function DateTimePicker(props) {
2994
3070
  }
2995
3071
  )
2996
3072
  ] }),
2997
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "fe-datetime-picker__weekdays", children: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((day) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: day }, day)) }),
3073
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "fe-datetime-picker__weekdays", children: text.weekdays.map((day) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: day }, day)) }),
2998
3074
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "fe-datetime-picker__days", children: days.map((day) => {
2999
3075
  const inMonth = day.getMonth() === month.getMonth();
3000
3076
  const selected = isRange ? sameDay(day, rangeValue[0]) || sameDay(day, rangeValue[1]) : sameDay(day, singleValue);
3001
3077
  const inRange = isRange && rangeValue[0] && rangeValue[1] && day > startOfDay(rangeValue[0]) && day < startOfDay(rangeValue[1]);
3078
+ const isToday = sameDay(day, today);
3002
3079
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3003
3080
  "button",
3004
3081
  {
3005
3082
  type: "button",
3083
+ "aria-current": isToday ? "date" : void 0,
3006
3084
  className: [
3007
3085
  !inMonth && "is-other-month",
3086
+ isToday && "is-today",
3008
3087
  selected && "is-selected",
3009
3088
  inRange && "is-in-range"
3010
3089
  ].filter(Boolean).join(" "),
@@ -3014,6 +3093,7 @@ function DateTimePicker(props) {
3014
3093
  day.toISOString()
3015
3094
  );
3016
3095
  }) }),
3096
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "fe-datetime-picker__footer", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", onClick: selectToday, children: text.today }) }),
3017
3097
  isRange && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "fe-datetime-picker__range-tabs", children: [
3018
3098
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3019
3099
  "button",
@@ -3021,7 +3101,7 @@ function DateTimePicker(props) {
3021
3101
  type: "button",
3022
3102
  className: !editingEnd ? "is-active" : "",
3023
3103
  onClick: () => setEditingEnd(false),
3024
- children: "Start"
3104
+ children: text.start
3025
3105
  }
3026
3106
  ),
3027
3107
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
@@ -3030,12 +3110,12 @@ function DateTimePicker(props) {
3030
3110
  type: "button",
3031
3111
  className: editingEnd ? "is-active" : "",
3032
3112
  onClick: () => setEditingEnd(true),
3033
- children: "End"
3113
+ children: text.end
3034
3114
  }
3035
3115
  )
3036
3116
  ] }),
3037
3117
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "fe-datetime-picker__time", children: [
3038
- "Time",
3118
+ text.time,
3039
3119
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3040
3120
  "input",
3041
3121
  {
package/dist/index.mjs CHANGED
@@ -1821,6 +1821,9 @@ var Selection = forwardRef9(
1821
1821
  disabled = false,
1822
1822
  name,
1823
1823
  onKeyDown,
1824
+ maxWidth,
1825
+ overflow = "ellipsis",
1826
+ style,
1824
1827
  "aria-label": ariaLabel,
1825
1828
  "aria-describedby": ariaDescribedBy,
1826
1829
  "aria-labelledby": ariaLabelledBy,
@@ -1831,6 +1834,7 @@ var Selection = forwardRef9(
1831
1834
  const listboxId = triggerId + "-listbox";
1832
1835
  const labelId = generatedId + "-label";
1833
1836
  const messageId2 = generatedId + "-message";
1837
+ const tooltipId = generatedId + "-tooltip";
1834
1838
  const fieldError = getFieldError(error, errorMessage);
1835
1839
  const hasError = fieldError !== void 0 && fieldError !== false && fieldError !== null;
1836
1840
  const resolvedDescription = description ?? helperText;
@@ -1857,6 +1861,26 @@ var Selection = forwardRef9(
1857
1861
  const [activeIndex, setActiveIndex] = useState11(0);
1858
1862
  const rootRef = useRef7(null);
1859
1863
  const menuRef = useRef7(null);
1864
+ const valueRef = useRef7(null);
1865
+ const [truncated, setTruncated] = useState11(false);
1866
+ const [hovered, setHovered] = useState11(false);
1867
+ const [focused, setFocused] = useState11(false);
1868
+ const showsTags = tag && multiple && selectedOptions.length > 0;
1869
+ const canTruncate = overflow === "ellipsis" && !showsTags && selectedOptions.length > 0;
1870
+ const selectedKey = selectedOptions.map((option) => String(option.value)).join("|");
1871
+ useLayoutEffect3(() => {
1872
+ const node = valueRef.current;
1873
+ if (!canTruncate || !node) {
1874
+ setTruncated(false);
1875
+ return;
1876
+ }
1877
+ const measure = () => setTruncated(node.scrollWidth > node.clientWidth + 1);
1878
+ measure();
1879
+ if (typeof ResizeObserver === "undefined") return;
1880
+ const observer = new ResizeObserver(measure);
1881
+ observer.observe(node);
1882
+ return () => observer.disconnect();
1883
+ }, [canTruncate, selectedKey]);
1860
1884
  const [menuPosition, setMenuPosition] = useState11(null);
1861
1885
  useEffect5(() => {
1862
1886
  const close = (event) => {
@@ -1921,6 +1945,12 @@ var Selection = forwardRef9(
1921
1945
  setQuery("");
1922
1946
  };
1923
1947
  const displayLabel = selectedOptions.length ? selectedOptions.map((option) => option.label) : null;
1948
+ const showTooltip = truncated && (hovered || focused) && !open;
1949
+ const renderLabels = () => displayLabel?.map((item, index) => /* @__PURE__ */ jsxs12("span", { children: [
1950
+ item,
1951
+ index < displayLabel.length - 1 ? ", " : ""
1952
+ ] }, index));
1953
+ const toPx = (length) => typeof length === "number" ? length + "px" : length;
1924
1954
  const onTriggerKeyDown = (event) => {
1925
1955
  onKeyDown?.(event);
1926
1956
  if (disabled) return;
@@ -1952,12 +1982,14 @@ var Selection = forwardRef9(
1952
1982
  className: [
1953
1983
  "fe-selection",
1954
1984
  "fe-selection--" + size,
1985
+ "fe-selection--" + overflow,
1955
1986
  open && "fe-selection--open",
1956
1987
  clearable && selectedOptions.length > 0 && "fe-selection--clearable",
1957
1988
  hasError && "fe-selection--error",
1958
1989
  disabled && "fe-selection--disabled",
1959
1990
  className
1960
1991
  ].filter(Boolean).join(" "),
1992
+ style: maxWidth === void 0 ? style : { ...style, maxWidth: toPx(maxWidth) },
1961
1993
  ...props,
1962
1994
  children: [
1963
1995
  /* @__PURE__ */ jsx15(
@@ -1991,16 +2023,24 @@ var Selection = forwardRef9(
1991
2023
  "aria-invalid": hasError || void 0,
1992
2024
  "aria-required": isRequired || void 0,
1993
2025
  "aria-labelledby": labelledBy,
1994
- "aria-describedby": describedBy,
2026
+ "aria-describedby": getDescribedBy(
2027
+ describedBy,
2028
+ showTooltip ? tooltipId : void 0
2029
+ ),
1995
2030
  "aria-haspopup": "listbox",
1996
2031
  "aria-expanded": open,
1997
2032
  "aria-controls": listboxId,
1998
2033
  onClick: () => setOpen((current) => !current),
1999
2034
  onKeyDown: onTriggerKeyDown,
2035
+ onMouseEnter: () => setHovered(true),
2036
+ onMouseLeave: () => setHovered(false),
2037
+ onFocus: () => setFocused(true),
2038
+ onBlur: () => setFocused(false),
2000
2039
  children: [
2001
2040
  /* @__PURE__ */ jsx15(
2002
2041
  "span",
2003
2042
  {
2043
+ ref: valueRef,
2004
2044
  className: [
2005
2045
  "fe-selection__value",
2006
2046
  !selectedOptions.length && "is-placeholder",
@@ -2016,10 +2056,7 @@ var Selection = forwardRef9(
2016
2056
  ]
2017
2057
  },
2018
2058
  String(option.value)
2019
- )) : displayLabel.map((item, index) => /* @__PURE__ */ jsxs12("span", { children: [
2020
- item,
2021
- index < displayLabel.length - 1 ? ", " : ""
2022
- ] }, index)) : /* @__PURE__ */ jsxs12(Fragment2, { children: [
2059
+ )) : renderLabels() : /* @__PURE__ */ jsxs12(Fragment2, { children: [
2023
2060
  /* @__PURE__ */ jsx15("span", { children: placeholder }),
2024
2061
  isRequired && /* @__PURE__ */ jsx15("span", { className: "fe-field__required", "aria-hidden": "true", children: "*" })
2025
2062
  ] })
@@ -2038,6 +2075,7 @@ var Selection = forwardRef9(
2038
2075
  onClick: clear
2039
2076
  }
2040
2077
  ),
2078
+ showTooltip && /* @__PURE__ */ jsx15("span", { id: tooltipId, role: "tooltip", className: "fe-selection__tooltip", children: renderLabels() }),
2041
2079
  open && menuPosition && createPortal2(
2042
2080
  /* @__PURE__ */ jsxs12(
2043
2081
  "div",
@@ -2089,7 +2127,7 @@ var Selection = forwardRef9(
2089
2127
  onMouseMove: () => setActiveIndex(index),
2090
2128
  onClick: () => choose(option),
2091
2129
  children: [
2092
- /* @__PURE__ */ jsx15("span", { children: option.label }),
2130
+ /* @__PURE__ */ jsx15("span", { className: "fe-selection__option-label", children: option.label }),
2093
2131
  isSelected && /* @__PURE__ */ jsx15(
2094
2132
  "span",
2095
2133
  {
@@ -2481,6 +2519,30 @@ function CurrencyInput({
2481
2519
  // packages/form-controls/src/controls/DateTimePicker/date-time-picker.tsx
2482
2520
  import { useEffect as useEffect7, useId as useId9, useRef as useRef9, useState as useState14 } from "react";
2483
2521
  import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
2522
+ var LABELS_EN = {
2523
+ weekdays: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
2524
+ today: "Today",
2525
+ time: "Time",
2526
+ start: "Start",
2527
+ end: "End",
2528
+ previousMonth: "Previous month",
2529
+ nextMonth: "Next month",
2530
+ dialog: "Date and time picker",
2531
+ selectDateTime: "Select date and time",
2532
+ selectDateRange: "Select date range"
2533
+ };
2534
+ var LABELS_VI = {
2535
+ weekdays: ["T2", "T3", "T4", "T5", "T6", "T7", "CN"],
2536
+ today: "H\xF4m nay",
2537
+ time: "Gi\u1EDD",
2538
+ start: "B\u1EAFt \u0111\u1EA7u",
2539
+ end: "K\u1EBFt th\xFAc",
2540
+ previousMonth: "Th\xE1ng tr\u01B0\u1EDBc",
2541
+ nextMonth: "Th\xE1ng sau",
2542
+ dialog: "Ch\u1ECDn ng\xE0y v\xE0 gi\u1EDD",
2543
+ selectDateTime: "Ch\u1ECDn ng\xE0y v\xE0 gi\u1EDD",
2544
+ selectDateRange: "Ch\u1ECDn kho\u1EA3ng ng\xE0y"
2545
+ };
2484
2546
  var pad = (value) => String(value).padStart(2, "0");
2485
2547
  function formatDate(date, format) {
2486
2548
  return format.replace(/yyyy/g, String(date.getFullYear())).replace(/MM/g, pad(date.getMonth() + 1)).replace(/dd/g, pad(date.getDate())).replace(/HH/g, pad(date.getHours())).replace(/mm/g, pad(date.getMinutes()));
@@ -2510,12 +2572,17 @@ function DateTimePicker(props) {
2510
2572
  disabled,
2511
2573
  placeholder,
2512
2574
  locale = "en-US",
2575
+ labels,
2513
2576
  className,
2514
2577
  mode = "single",
2515
2578
  id,
2516
2579
  "aria-describedby": ariaDescribedBy,
2517
2580
  "aria-labelledby": ariaLabelledBy
2518
2581
  } = props;
2582
+ const text = {
2583
+ ...locale.toLowerCase().startsWith("vi") ? LABELS_VI : LABELS_EN,
2584
+ ...labels
2585
+ };
2519
2586
  const generatedId = useId9();
2520
2587
  const triggerId = id ?? generatedId + "-trigger";
2521
2588
  const labelId = generatedId + "-label";
@@ -2603,6 +2670,15 @@ function DateTimePicker(props) {
2603
2670
  { length: 42 },
2604
2671
  (_, index) => new Date(month.getFullYear(), month.getMonth(), index - offset + 1)
2605
2672
  );
2673
+ const today = /* @__PURE__ */ new Date();
2674
+ const selectToday = () => {
2675
+ setMonth(today);
2676
+ selectDay(today);
2677
+ };
2678
+ const toggleOpen = () => {
2679
+ if (!open) setMonth((isRange ? rangeValue[0] : singleValue) ?? today);
2680
+ setOpen(!open);
2681
+ };
2606
2682
  const selectedForTime = isRange ? editingEnd ? rangeValue[1] : rangeValue[0] : singleValue;
2607
2683
  const setTime = (time) => {
2608
2684
  if (!selectedForTime) return;
@@ -2643,7 +2719,7 @@ function DateTimePicker(props) {
2643
2719
  "aria-labelledby": labelledBy,
2644
2720
  "aria-describedby": describedBy,
2645
2721
  "aria-expanded": open,
2646
- onClick: () => setOpen((current) => !current),
2722
+ onClick: toggleOpen,
2647
2723
  children: [
2648
2724
  /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", children: "\u25F7" }),
2649
2725
  /* @__PURE__ */ jsxs14(
@@ -2651,7 +2727,7 @@ function DateTimePicker(props) {
2651
2727
  {
2652
2728
  className: !shownValue && placeholder ? "fe-datetime-picker__value is-placeholder" : "fe-datetime-picker__value",
2653
2729
  children: [
2654
- shownValue || placeholder || (isRange ? "Select date range" : "Select date and time"),
2730
+ shownValue || placeholder || (isRange ? text.selectDateRange : text.selectDateTime),
2655
2731
  isRequired && placeholder && !shownValue && /* @__PURE__ */ jsx18("span", { className: "fe-field__required", "aria-hidden": "true", children: "*" })
2656
2732
  ]
2657
2733
  }
@@ -2664,14 +2740,14 @@ function DateTimePicker(props) {
2664
2740
  {
2665
2741
  className: "fe-datetime-picker__popper",
2666
2742
  role: "dialog",
2667
- "aria-label": "Date and time picker",
2743
+ "aria-label": text.dialog,
2668
2744
  children: [
2669
2745
  /* @__PURE__ */ jsxs14("div", { className: "fe-datetime-picker__month", children: [
2670
2746
  /* @__PURE__ */ jsx18(
2671
2747
  "button",
2672
2748
  {
2673
2749
  type: "button",
2674
- "aria-label": "Previous month",
2750
+ "aria-label": text.previousMonth,
2675
2751
  onClick: () => setMonth(
2676
2752
  (current) => new Date(current.getFullYear(), current.getMonth() - 1, 1)
2677
2753
  ),
@@ -2686,7 +2762,7 @@ function DateTimePicker(props) {
2686
2762
  "button",
2687
2763
  {
2688
2764
  type: "button",
2689
- "aria-label": "Next month",
2765
+ "aria-label": text.nextMonth,
2690
2766
  onClick: () => setMonth(
2691
2767
  (current) => new Date(current.getFullYear(), current.getMonth() + 1, 1)
2692
2768
  ),
@@ -2694,17 +2770,20 @@ function DateTimePicker(props) {
2694
2770
  }
2695
2771
  )
2696
2772
  ] }),
2697
- /* @__PURE__ */ jsx18("div", { className: "fe-datetime-picker__weekdays", children: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((day) => /* @__PURE__ */ jsx18("span", { children: day }, day)) }),
2773
+ /* @__PURE__ */ jsx18("div", { className: "fe-datetime-picker__weekdays", children: text.weekdays.map((day) => /* @__PURE__ */ jsx18("span", { children: day }, day)) }),
2698
2774
  /* @__PURE__ */ jsx18("div", { className: "fe-datetime-picker__days", children: days.map((day) => {
2699
2775
  const inMonth = day.getMonth() === month.getMonth();
2700
2776
  const selected = isRange ? sameDay(day, rangeValue[0]) || sameDay(day, rangeValue[1]) : sameDay(day, singleValue);
2701
2777
  const inRange = isRange && rangeValue[0] && rangeValue[1] && day > startOfDay(rangeValue[0]) && day < startOfDay(rangeValue[1]);
2778
+ const isToday = sameDay(day, today);
2702
2779
  return /* @__PURE__ */ jsx18(
2703
2780
  "button",
2704
2781
  {
2705
2782
  type: "button",
2783
+ "aria-current": isToday ? "date" : void 0,
2706
2784
  className: [
2707
2785
  !inMonth && "is-other-month",
2786
+ isToday && "is-today",
2708
2787
  selected && "is-selected",
2709
2788
  inRange && "is-in-range"
2710
2789
  ].filter(Boolean).join(" "),
@@ -2714,6 +2793,7 @@ function DateTimePicker(props) {
2714
2793
  day.toISOString()
2715
2794
  );
2716
2795
  }) }),
2796
+ /* @__PURE__ */ jsx18("div", { className: "fe-datetime-picker__footer", children: /* @__PURE__ */ jsx18("button", { type: "button", onClick: selectToday, children: text.today }) }),
2717
2797
  isRange && /* @__PURE__ */ jsxs14("div", { className: "fe-datetime-picker__range-tabs", children: [
2718
2798
  /* @__PURE__ */ jsx18(
2719
2799
  "button",
@@ -2721,7 +2801,7 @@ function DateTimePicker(props) {
2721
2801
  type: "button",
2722
2802
  className: !editingEnd ? "is-active" : "",
2723
2803
  onClick: () => setEditingEnd(false),
2724
- children: "Start"
2804
+ children: text.start
2725
2805
  }
2726
2806
  ),
2727
2807
  /* @__PURE__ */ jsx18(
@@ -2730,12 +2810,12 @@ function DateTimePicker(props) {
2730
2810
  type: "button",
2731
2811
  className: editingEnd ? "is-active" : "",
2732
2812
  onClick: () => setEditingEnd(true),
2733
- children: "End"
2813
+ children: text.end
2734
2814
  }
2735
2815
  )
2736
2816
  ] }),
2737
2817
  /* @__PURE__ */ jsxs14("label", { className: "fe-datetime-picker__time", children: [
2738
- "Time",
2818
+ text.time,
2739
2819
  /* @__PURE__ */ jsx18(
2740
2820
  "input",
2741
2821
  {
package/dist/styles.css CHANGED
@@ -886,8 +886,9 @@ table[data-fe-table][data-resizing] {
886
886
  display: flex;
887
887
  align-items: center;
888
888
  width: 100%;
889
+ min-width: 0;
889
890
  min-height: 40px;
890
- padding: 0 13px;
891
+ padding: 0 40px 0 13px;
891
892
  border: 1px solid #d4d8e0;
892
893
  border-radius: 12px;
893
894
  outline: 0;
@@ -902,7 +903,11 @@ table[data-fe-table][data-resizing] {
902
903
  background 0.15s;
903
904
  }
904
905
  .fe-selection--clearable .fe-selection__trigger {
905
- padding-right: 64px;
906
+ padding-right: 72px;
907
+ }
908
+ .fe-selection--wrap .fe-selection__trigger {
909
+ padding-top: 8px;
910
+ padding-bottom: 8px;
906
911
  }
907
912
  .fe-selection--small .fe-selection__trigger {
908
913
  min-height: 34px;
@@ -922,19 +927,24 @@ table[data-fe-table][data-resizing] {
922
927
  box-shadow: 0 0 0 3px rgba(40, 120, 240, 0.12);
923
928
  }
924
929
  .fe-selection__value {
925
- display: flex;
930
+ display: block;
926
931
  width: 100%;
927
932
  min-width: 0;
928
933
  flex: 1 1 auto;
929
- align-items: center;
930
934
  overflow: hidden;
931
935
  text-overflow: ellipsis;
932
936
  white-space: nowrap;
933
937
  }
938
+ .fe-selection--wrap .fe-selection__value {
939
+ line-height: 1.4;
940
+ overflow-wrap: anywhere;
941
+ white-space: normal;
942
+ }
934
943
  .fe-selection__value.is-placeholder {
935
944
  color: #8b94a4;
936
945
  }
937
946
  .fe-selection__value.is-tags {
947
+ display: flex;
938
948
  flex-wrap: wrap;
939
949
  align-content: center;
940
950
  gap: 5px;
@@ -1013,6 +1023,24 @@ table[data-fe-table][data-resizing] {
1013
1023
  outline: 2px solid #2878f0;
1014
1024
  outline-offset: 1px;
1015
1025
  }
1026
+ .fe-selection__tooltip {
1027
+ position: absolute;
1028
+ z-index: 50;
1029
+ bottom: calc(100% + 8px);
1030
+ left: 0;
1031
+ width: max-content;
1032
+ max-width: min(320px, calc(100vw - 32px));
1033
+ padding: 7px 9px;
1034
+ border-radius: 7px;
1035
+ background: #20242c;
1036
+ color: #fff;
1037
+ font-size: 12px;
1038
+ font-weight: 500;
1039
+ line-height: 1.35;
1040
+ overflow-wrap: anywhere;
1041
+ box-shadow: 0 5px 18px rgba(0, 0, 0, 0.22);
1042
+ pointer-events: none;
1043
+ }
1016
1044
  .fe-selection__chevron {
1017
1045
  position: absolute;
1018
1046
  top: 2px;
@@ -1073,6 +1101,7 @@ table[data-fe-table][data-resizing] {
1073
1101
  display: flex;
1074
1102
  align-items: center;
1075
1103
  justify-content: space-between;
1104
+ gap: 8px;
1076
1105
  width: 100%;
1077
1106
  min-height: 37px;
1078
1107
  padding: 8px 10px;
@@ -1098,7 +1127,12 @@ table[data-fe-table][data-resizing] {
1098
1127
  opacity: 0.45;
1099
1128
  cursor: not-allowed;
1100
1129
  }
1130
+ .fe-selection__option-label {
1131
+ min-width: 0;
1132
+ overflow-wrap: anywhere;
1133
+ }
1101
1134
  .fe-selection__check {
1135
+ flex: none;
1102
1136
  font-weight: 800;
1103
1137
  }
1104
1138
  .fe-selection__empty {
@@ -1677,6 +1711,34 @@ table[data-fe-table][data-resizing] {
1677
1711
  .fe-datetime-picker__days button.is-other-month {
1678
1712
  color: #aab0bb;
1679
1713
  }
1714
+ .fe-datetime-picker__days button.is-today {
1715
+ box-shadow: inset 0 0 0 1.5px #2878f0;
1716
+ color: #1e60cc;
1717
+ font-weight: 700;
1718
+ }
1719
+ .fe-datetime-picker__days button.is-today.is-selected {
1720
+ box-shadow: inset 0 0 0 1.5px #2878f0, inset 0 0 0 3px #fff;
1721
+ color: #fff;
1722
+ }
1723
+ .fe-datetime-picker__footer {
1724
+ display: flex;
1725
+ justify-content: center;
1726
+ margin-top: 8px;
1727
+ }
1728
+ .fe-datetime-picker__footer button {
1729
+ padding: 5px 12px;
1730
+ border: 0;
1731
+ border-radius: 8px;
1732
+ background: transparent;
1733
+ color: #1e60cc;
1734
+ font: inherit;
1735
+ font-size: 13px;
1736
+ font-weight: 600;
1737
+ cursor: pointer;
1738
+ }
1739
+ .fe-datetime-picker__footer button:hover {
1740
+ background: #f0f5ff;
1741
+ }
1680
1742
  .fe-datetime-picker__range-tabs {
1681
1743
  display: flex;
1682
1744
  gap: 4px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dragunio/fe-libs",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Reusable React components, icons, and table primitives.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -93,4 +93,4 @@
93
93
  "public"
94
94
  ]
95
95
  }
96
- }
96
+ }