@olundot/ui 0.17.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @olundot/ui
2
2
 
3
+ ## 0.17.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 6d9f93c: 연속 로드 목록(#1746) 준비물과 버그 수정. 새 prop은 모두 선택 사항이라, 주지 않으면 기존 화면의 마크업과 동작이 0.17.0과 같습니다. 기존 화면에서 달라지는 것은 아래 "수정" 항목뿐입니다.
8
+
9
+ - `BulkActionBar` `trailing`: 선택 해제(✕) 뒤에 붙는 자리입니다. 편집 모드의 [완료]처럼 선택과 별개인 컨트롤을 둡니다. inline 띠와 floating pill 모두 ✕ 바로 뒤이고, 선택 전 상태 줄(`idleContent`)에서는 오른쪽 끝입니다. 상태 줄에 `trailing`이 있으면 `role="status"`는 개수 텍스트에만 붙고 버튼은 라이브 영역 밖에 둡니다(불러올 때마다 개수만 다시 읽힙니다).
10
+ - `DataTable` `virtual.onRangeChange({ start, end })`: 보이는 행 범위(overscan 제외, `end` 제외)를 범위나 불러온 행 수가 바뀔 때 알립니다. 빠르게 스크롤해 지나친 행은 보고되지 않지만 `end`는 도착한 위치를 그대로 반영하므로, 미리 요청은 `end >= data.length - 30` 같은 문턱 비교로 씁니다.
11
+ - `DataTable` `virtual.handleRef` → `scrollToIndex(index)`: 그 행을 스크롤 컨테이너 맨 위(데스크톱은 sticky 열 머리 바로 아래)로 옮깁니다. 새로고침 복원용입니다. `DataTableVirtualRange`·`DataTableVirtualHandle` 타입을 export합니다.
12
+ - `DataTable` `selectionUnit`(기본 "개")·`announceSelection`(기본 `true`): sr-only 선택 안내의 단위를 바꾸거나 끕니다. inline `BulkActionBar`가 개수를 이미 읽어 줄 때, 또는 불러오지 않은 행까지 선택할 때(내장 안내는 불러온 행만 셉니다) 끕니다.
13
+ - 수정 — `BulkActionBar` inline `summary` 칸: 긴 문구를 자르는 칸이 28px 높이·좌우 3px 여백이라, 좁은 띠에서 `compactSummary`로 둔 `IconButton`의 44px 터치 영역이 위아래·왼쪽으로 잘렸습니다. 칸을 터치 영역 높이(44px)로 두고 왼쪽 여백을 8px로 넓혔습니다. 띠 높이 40px, 텍스트 잘림, `compactSummary` 전환은 그대로입니다.
14
+
3
15
  ## 0.17.0
4
16
 
5
17
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -32,8 +32,8 @@ declare function useOlunTheme(): UseOlunThemeValue;
32
32
  type SurfaceLevel = "surface" | "canvas" | "raised";
33
33
 
34
34
  declare const buttonVariants: (props?: ({
35
- variant?: "default" | "primary" | "outline" | "ghost" | "danger" | "emergency" | "subtle" | "destructive" | "secondary" | "link" | null | undefined;
36
- size?: "default" | "xs" | "sm" | "md" | "lg" | "xl" | "icon" | "icon-xs" | null | undefined;
35
+ variant?: "primary" | "secondary" | "destructive" | "default" | "outline" | "ghost" | "danger" | "emergency" | "subtle" | "link" | null | undefined;
36
+ size?: "xs" | "sm" | "md" | "lg" | "xl" | "default" | "icon" | "icon-xs" | null | undefined;
37
37
  } & class_variance_authority_types.ClassProp) | undefined) => string;
38
38
  type ButtonVariant = NonNullable<VariantProps<typeof buttonVariants>['variant']>;
39
39
  type ButtonSize = NonNullable<VariantProps<typeof buttonVariants>['size']>;
@@ -54,7 +54,7 @@ type CopyButtonProps = Omit<ButtonProps, 'children' | 'leadingIcon' | 'loading'
54
54
  variant?: ButtonVariant;
55
55
  duration?: number;
56
56
  };
57
- declare const CopyButton: React.ForwardRefExoticComponent<Omit<ButtonProps, "size" | "variant" | "leadingIcon" | "trailingIcon" | "loading" | "children"> & {
57
+ declare const CopyButton: React.ForwardRefExoticComponent<Omit<ButtonProps, "variant" | "size" | "leadingIcon" | "trailingIcon" | "loading" | "children"> & {
58
58
  value: string;
59
59
  label?: React.ReactNode;
60
60
  copiedLabel?: React.ReactNode;
@@ -70,7 +70,7 @@ declare const inputVariants: (props?: ({
70
70
  surface?: SurfaceLevel | null | undefined;
71
71
  } & class_variance_authority_types.ClassProp) | undefined) => string;
72
72
  declare const inputMessageVariants: (props?: ({
73
- state?: "default" | "error" | "success" | null | undefined;
73
+ state?: "error" | "success" | "default" | null | undefined;
74
74
  size?: "sm" | "md" | "lg" | null | undefined;
75
75
  } & class_variance_authority_types.ClassProp) | undefined) => string;
76
76
  type InputState = NonNullable<VariantProps<typeof inputMessageVariants>["state"]>;
@@ -119,11 +119,11 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "
119
119
  declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
120
120
 
121
121
  declare const fileUploadZoneVariants: (props?: ({
122
- size?: "default" | "compact" | null | undefined;
122
+ size?: "compact" | "default" | null | undefined;
123
123
  surface?: SurfaceLevel | null | undefined;
124
124
  } & class_variance_authority_types.ClassProp) | undefined) => string;
125
125
  declare const fileUploadIconVariants: (props?: ({
126
- size?: "default" | "compact" | null | undefined;
126
+ size?: "compact" | "default" | null | undefined;
127
127
  } & class_variance_authority_types.ClassProp) | undefined) => string;
128
128
  interface FileUploadZoneProps extends Omit<React.LabelHTMLAttributes<HTMLLabelElement>, "onChange">, VariantProps<typeof fileUploadZoneVariants> {
129
129
  accept?: string;
@@ -166,7 +166,7 @@ declare const textareaVariants: (props?: ({
166
166
  surface?: SurfaceLevel | null | undefined;
167
167
  } & class_variance_authority_types.ClassProp) | undefined) => string;
168
168
  declare const textareaMessageVariants: (props?: ({
169
- state?: "default" | "error" | "success" | null | undefined;
169
+ state?: "error" | "success" | "default" | null | undefined;
170
170
  } & class_variance_authority_types.ClassProp) | undefined) => string;
171
171
  type TextareaState = NonNullable<VariantProps<typeof textareaMessageVariants>["state"]>;
172
172
  /** Canonical size type (0.2.0+). Use `size` prop with these values. */
@@ -221,7 +221,7 @@ declare const selectVariants: (props?: ({
221
221
  surface?: SurfaceLevel | null | undefined;
222
222
  } & class_variance_authority_types.ClassProp) | undefined) => string;
223
223
  declare const selectMessageVariants: (props?: ({
224
- state?: "default" | "error" | "success" | null | undefined;
224
+ state?: "error" | "success" | "default" | null | undefined;
225
225
  size?: "sm" | "md" | "lg" | null | undefined;
226
226
  } & class_variance_authority_types.ClassProp) | undefined) => string;
227
227
  type SelectState = NonNullable<VariantProps<typeof selectMessageVariants>["state"]>;
@@ -706,9 +706,30 @@ interface DataTableLinkProps {
706
706
  children?: React.ReactNode;
707
707
  'data-slot'?: string;
708
708
  }
709
+ /** Visible rows as `data` indexes: `start` inclusive, `end` exclusive (like `slice`). */
710
+ interface DataTableVirtualRange {
711
+ start: number;
712
+ end: number;
713
+ }
714
+ interface DataTableVirtualHandle {
715
+ /**
716
+ * Scrolls the list's scroll container so row `index` (clamped to the loaded rows)
717
+ * sits at its top — under the sticky header on desktop. For restoring a position.
718
+ */
719
+ scrollToIndex: (index: number) => void;
720
+ }
709
721
  interface DataTableVirtualOptions {
710
722
  /** Rows rendered past each viewport edge. Default 8. */
711
723
  overscan?: number;
724
+ /**
725
+ * Called with the rows actually visible (not the overscan) whenever that range or
726
+ * the number of loaded rows changes. Scrolling is sampled once per frame, so a fast
727
+ * scroll can skip rows — compare with a threshold (`end >= data.length - 30`), not
728
+ * equality with one row.
729
+ */
730
+ onRangeChange?: (range: DataTableVirtualRange) => void;
731
+ /** Receives `{ scrollToIndex }`. */
732
+ handleRef?: React.Ref<DataTableVirtualHandle>;
712
733
  }
713
734
  interface DataTableSort {
714
735
  key: string;
@@ -721,6 +742,15 @@ interface DataTableProps<T> extends Omit<React.HTMLAttributes<HTMLDivElement>, '
721
742
  selectable?: boolean;
722
743
  selectedIds?: Set<string>;
723
744
  onSelectionChange?: (ids: Set<string>) => void;
745
+ /** Unit in the screen-reader selection message — `12명 선택됨`. Defaults to `개`. */
746
+ selectionUnit?: string;
747
+ /**
748
+ * `false` drops the built-in screen-reader selection message — when a
749
+ * `BulkActionBar placement="inline"` already announces the count (it is a status
750
+ * region), or when the real selection includes rows that are not loaded (the
751
+ * built-in message only counts loaded rows). Default `true`.
752
+ */
753
+ announceSelection?: boolean;
724
754
  activeRowId?: string;
725
755
  onRowContextMenu?: (rowId: string, event: React.MouseEvent) => void;
726
756
  sortBy?: DataTableSort;
@@ -836,6 +866,12 @@ interface BulkActionBarProps extends React.HTMLAttributes<HTMLDivElement> {
836
866
  * Takes precedence over `emptyHint`; with neither, the bar hides at count 0.
837
867
  */
838
868
  idleContent?: React.ReactNode;
869
+ /**
870
+ * After the clear (✕) button — e.g. an edit-mode "완료" button. On the idle line it
871
+ * sits at the right end, outside the `role="status"` region, so it is not re-read
872
+ * whenever `idleContent` changes. Same spot in both placements.
873
+ */
874
+ trailing?: React.ReactNode;
839
875
  }
840
876
  /**
841
877
  * OLUN BulkActionBar — multi-select table/list actions.
@@ -843,7 +879,8 @@ interface BulkActionBarProps extends React.HTMLAttributes<HTMLDivElement> {
843
879
  * placement="floating" (default) is the bottom pill; placement="inline" is a
844
880
  * top-sticky band that replaces the status line under the toolbar, so it comes
845
881
  * before the rows in tab order. `unit` sets the count unit, `summary` holds a
846
- * suggestion next to the count, `idleContent` shows while nothing is selected.
882
+ * suggestion next to the count, `idleContent` shows while nothing is selected,
883
+ * `trailing` follows the clear button (right end of the idle line).
847
884
  * Inline, the band and the idle line are one 40px line: a long `summary` is
848
885
  * clipped or swapped for `compactSummary`, never wrapped.
849
886
  *
@@ -859,7 +896,7 @@ interface BulkActionBarProps extends React.HTMLAttributes<HTMLDivElement> {
859
896
  * { key: "del", label: "삭제", variant: "destructive", onClick: confirmDelete },
860
897
  * ]} />
861
898
  */
862
- declare function BulkActionBar({ count, actions, onClear, emptyHint, placement, unit, summary, compactSummary, idleContent, className, style, ...props }: BulkActionBarProps): react_jsx_runtime.JSX.Element | null;
899
+ declare function BulkActionBar({ count, actions, onClear, emptyHint, placement, unit, summary, compactSummary, idleContent, trailing, className, style, ...props }: BulkActionBarProps): react_jsx_runtime.JSX.Element | null;
863
900
 
864
901
  declare const Dialog: React.FC<Dialog$1.DialogProps>;
865
902
  declare const DialogTrigger: React.ForwardRefExoticComponent<Dialog$1.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
@@ -1092,12 +1129,12 @@ declare const NotificationBadge: React.ForwardRefExoticComponent<NotificationBad
1092
1129
 
1093
1130
  declare const chipVariants: (props?: ({
1094
1131
  variant?: "filter" | "choice" | "removable" | "status-filter" | null | undefined;
1095
- tone?: "accent" | "danger" | "success" | "warning" | "neutral" | "muted" | null | undefined;
1132
+ tone?: "muted" | "accent" | "warning" | "success" | "neutral" | "danger" | null | undefined;
1096
1133
  size?: "sm" | "md" | "lg" | null | undefined;
1097
1134
  pressed?: boolean | null | undefined;
1098
1135
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1099
1136
  declare const chipCountVariants: (props?: ({
1100
- tone?: "accent" | "danger" | "success" | "warning" | "neutral" | "muted" | null | undefined;
1137
+ tone?: "muted" | "accent" | "warning" | "success" | "neutral" | "danger" | null | undefined;
1101
1138
  size?: "sm" | "md" | "lg" | null | undefined;
1102
1139
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1103
1140
  type ChipVariant = NonNullable<VariantProps<typeof chipVariants>["variant"]>;
@@ -1336,7 +1373,7 @@ interface ActionFooterProps extends Omit<React.HTMLAttributes<HTMLDivElement>, '
1336
1373
  declare const ActionFooter: React.ForwardRefExoticComponent<ActionFooterProps & React.RefAttributes<HTMLDivElement>>;
1337
1374
 
1338
1375
  declare const toastVariants: (props?: ({
1339
- variant?: "default" | "error" | "success" | "info" | "warning" | null | undefined;
1376
+ variant?: "error" | "warning" | "info" | "success" | "default" | null | undefined;
1340
1377
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1341
1378
  declare const toastViewportVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
1342
1379
  type ToastVariant = NonNullable<VariantProps<typeof toastVariants>['variant']>;
@@ -1390,19 +1427,19 @@ interface ToastProviderProps extends React.HTMLAttributes<HTMLDivElement> {
1390
1427
  declare function ToastProvider({ children, maxToasts, className, ...props }: ToastProviderProps): react_jsx_runtime.JSX.Element;
1391
1428
 
1392
1429
  declare const otpFieldVariants: (props?: ({
1393
- size?: "default" | "compact" | null | undefined;
1430
+ size?: "compact" | "default" | null | undefined;
1394
1431
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1395
1432
  declare const otpFieldGroupVariants: (props?: ({
1396
- size?: "default" | "compact" | null | undefined;
1433
+ size?: "compact" | "default" | null | undefined;
1397
1434
  fluid?: boolean | null | undefined;
1398
1435
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1399
1436
  declare const otpCellVariants: (props?: ({
1400
- size?: "default" | "compact" | null | undefined;
1437
+ size?: "compact" | "default" | null | undefined;
1401
1438
  fluid?: boolean | null | undefined;
1402
1439
  surface?: SurfaceLevel | null | undefined;
1403
1440
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1404
1441
  declare const otpFieldMessageVariants: (props?: ({
1405
- state?: "default" | "error" | null | undefined;
1442
+ state?: "error" | "default" | null | undefined;
1406
1443
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1407
1444
  type OTPFieldSize = NonNullable<VariantProps<typeof otpCellVariants>["size"]>;
1408
1445
  interface OTPFieldProps extends Omit<React.FieldsetHTMLAttributes<HTMLFieldSetElement>, "onChange" | "children" | "defaultValue" | "value">, VariantProps<typeof otpFieldVariants> {
@@ -1459,11 +1496,11 @@ declare const checkboxBoxVariants: (props?: ({
1459
1496
  size?: "sm" | "md" | null | undefined;
1460
1497
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1461
1498
  declare const checkboxGroupItemVariants: (props?: ({
1462
- appearance?: "plain" | "card" | null | undefined;
1499
+ appearance?: "card" | "plain" | null | undefined;
1463
1500
  density?: "compact" | "comfortable" | null | undefined;
1464
1501
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1465
1502
  declare const checkboxGroupBoxVariants: (props?: ({
1466
- appearance?: "plain" | "card" | null | undefined;
1503
+ appearance?: "card" | "plain" | null | undefined;
1467
1504
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1468
1505
  type CheckboxSize = NonNullable<VariantProps<typeof checkboxBoxVariants>["size"]>;
1469
1506
  type CheckboxCheckedState = React.ComponentProps<typeof Checkbox$1.Root>["checked"];
@@ -1488,7 +1525,7 @@ interface CheckboxProps extends Omit<React.ComponentPropsWithoutRef<typeof Check
1488
1525
  declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLButtonElement>>;
1489
1526
 
1490
1527
  declare const checkboxGroupVariants: (props?: ({
1491
- appearance?: "plain" | "card" | null | undefined;
1528
+ appearance?: "card" | "plain" | null | undefined;
1492
1529
  orientation?: "horizontal" | "vertical" | null | undefined;
1493
1530
  columns?: "one" | "two" | "three" | null | undefined;
1494
1531
  } & class_variance_authority_types.ClassProp) | undefined) => string;
@@ -1509,16 +1546,16 @@ interface CheckboxGroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
1509
1546
  declare const CheckboxGroup: React.ForwardRefExoticComponent<CheckboxGroupProps & React.RefAttributes<HTMLDivElement>>;
1510
1547
 
1511
1548
  declare const radioGroupVariants: (props?: ({
1512
- appearance?: "plain" | "card" | null | undefined;
1549
+ appearance?: "card" | "plain" | null | undefined;
1513
1550
  orientation?: "horizontal" | "vertical" | null | undefined;
1514
1551
  columns?: "one" | "two" | "three" | null | undefined;
1515
1552
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1516
1553
  declare const radioVariants: (props?: ({
1517
- appearance?: "plain" | "card" | null | undefined;
1554
+ appearance?: "card" | "plain" | null | undefined;
1518
1555
  density?: "compact" | "comfortable" | null | undefined;
1519
1556
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1520
1557
  declare const radioControlVariants: (props?: ({
1521
- appearance?: "plain" | "card" | null | undefined;
1558
+ appearance?: "card" | "plain" | null | undefined;
1522
1559
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1523
1560
  type RadioGroupAppearance = NonNullable<VariantProps<typeof radioGroupVariants>["appearance"]>;
1524
1561
  type RadioGroupColumns = NonNullable<VariantProps<typeof radioGroupVariants>["columns"]>;
@@ -1655,4 +1692,4 @@ interface OrganizationLogoProps extends Omit<SVGProps<SVGSVGElement>, "width" |
1655
1692
  }
1656
1693
  declare function OrganizationLogo({ organization, size, className, style, role, "aria-label": ariaLabel, "aria-hidden": ariaHidden, ...props }: OrganizationLogoProps): react_jsx_runtime.JSX.Element;
1657
1694
 
1658
- export { ActionFooter, type ActionFooterAction, type ActionFooterProps, type ActionFooterStatus, Alert, type AlertEmphasis, type AlertProps, type AlertVariant, Avatar, AvatarFallback, type AvatarFallbackProps, AvatarImage, Badge, type BadgeProps, type BadgeTone, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, BulkActionBar, type BulkActionBarAction, type BulkActionBarProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardProse, CardTitle, type CardVariant, type CardVariantOptions, Checkbox, type CheckboxCheckedState, CheckboxGroup, type CheckboxGroupAppearance, type CheckboxGroupColumns, CheckboxGroupContext, type CheckboxGroupContextValue, type CheckboxGroupDensity, type CheckboxGroupOrientation, type CheckboxGroupProps, type CheckboxProps, type CheckboxSize, Chip, type ChipProps, type ChipSize, type ChipTone, type ChipVariant, ConfirmDialog, type ConfirmDialogProps, ContextMenu, type ContextMenuPosition, type ContextMenuProps, CopyButton, type CopyButtonProps, DataLayout, type DataLayoutProps, DataTable, type DataTableColumn, type DataTableLinkProps, type DataTableProps, type DataTableSort, type DataTableVirtualOptions, DetailLayout, type DetailLayoutProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogEyebrow, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogRawContent, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, type EmptyStateSize, type EmptyStateTone, type EmptyStateVariantOptions, ErrorState, type ErrorStateProps, FileUploadZone, type FileUploadZoneProps, FilterToolbar, type FilterToolbarCollapseBelow, type FilterToolbarProps, FormField, type FormFieldProps, type FormFieldRenderProps, FormLayout, type FormLayoutProps, type FormLayoutSection, FormModal, type FormModalProps, IconButton, type IconButtonBadgeTone, type IconButtonProps, type IconButtonSize, type IconButtonVariant, InfoModal, type InfoModalProps, InlineAlert, type InlineAlertProps, type InlineAlertSurface, Input, type InputProps, type InputSize, type InputSizeLegacy, type InputState, Label, type LabelProps, ModeToggle, type ModeToggleOption, type ModeToggleProps, NotificationBadge, type NotificationBadgePlacement, type NotificationBadgeProps, type NotificationBadgeSize, OTPField, type OTPFieldProps, type OTPFieldSize, OlunLogo, OlunSymbol, type OlunTheme, type OlunThemeDuration, type OlunThemeState, OrganizationLogo, type OrganizationLogoId, type OrganizationLogoProps, PageHeader, type PageHeaderProps, PageSizeSelect, type PageSizeSelectProps, type PageSizeSelectSize, Pagination, type PaginationProps, type PaginationSize, PermissionContext, type PermissionEvaluator, type PermissionFallback, PermissionGuard, type PermissionGuardProps, PermissionProvider, type PermissionProviderProps, type PermissionScope, type PermissionState, Popover, PopoverAnchor, PopoverArrow, PopoverClose, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, Progress, type ProgressProps, type ProgressStatus, Radio, RadioGroup, type RadioGroupAppearance, type RadioGroupColumns, type RadioGroupDensity, type RadioGroupOrientation, type RadioGroupProps, type RadioProps, ScrollArea, ScrollBar, SearchField, type SearchFieldProps, type SearchFieldSize, Select, type SelectAppearance, type SelectOption, type SelectProps, type SelectSize, type SelectState, type SelectVariant, type SemanticRole, Separator, type SetOlunThemeOptions, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetDrawer, type SheetDrawerProps, SheetFooter, SheetHeader, type SheetMotionConfig, type SheetMotionDuration, type SheetMotionEasing, type SheetMotionType, SheetTitle, SheetTrigger, Skeleton, type SkeletonProps, SkeletonRow, type SkeletonRowColumn, type SkeletonRowProps, SkeletonText, type SkeletonTextProps, Spinner, type SpinnerProps, StatusBadge, type StatusBadgeEmphasis, type StatusBadgeProps, type StatusBadgeSize, type StatusBadgeStatus, type SurfaceLevel, Switch, type SwitchProps, type TabItem, Tabs, TabsContent, type TabsProps, type TabsVariant, Textarea, type TextareaProps, type TextareaSize, type TextareaSizeLegacy, type TextareaState, ThemeFab, type ThemeFabProps, ThemeToggle, Toast, type ToastAction, type ToastItem, type ToastOptions, ToastProvider, ToastRoot, type ToastVariant, ToastViewport, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type TreeItemRowVariantProps, type TreeItemState, type TreeNode, TreeView, type TreeViewProps, TwoTierBadge, type TwoTierBadgeEmphasis, type TwoTierBadgeProps, type TwoTierBadgeSize, type TwoTierBadgeTone, type UseOlunThemeValue, WizardLayout, type WizardLayoutProps, type WizardStep, type WizardStepState, actionFooterStatusVariants, actionFooterVariants, buttonVariants, cardVariants, checkboxBoxVariants, checkboxFieldVariants, checkboxGroupBoxVariants, checkboxGroupItemVariants, checkboxGroupVariants, checkboxRootVariants, checkboxVariants, chipCountVariants, chipVariants, cn, dataTableRowVariants, dataTableVariants, emptyStateIconVariants, emptyStateVariants, errorStateVariants, evaluatePermission, fileUploadIconVariants, fileUploadZoneVariants, formFieldControlStackClassName, formFieldDescriptionClassName, formFieldErrorClassName, formFieldLabelClassName, formFieldRequiredClassName, formFieldVariants, getOlunThemeState, getToastDuration, iconButtonBadgeVariants, iconButtonVariants, inputMessageVariants, inputVariants, limitToasts, modeToggleItemVariants, modeToggleVariants, notificationBadgeVariants, otpCellVariants, otpFieldGroupVariants, otpFieldMessageVariants, otpFieldVariants, paginationControlVariants, paginationVariants, radioControlVariants, radioGroupVariants, radioVariants, searchFieldInputVariants, searchFieldVariants, selectMessageVariants, selectVariants, setOlunTheme, skeletonVariants, spinnerVariants, tabsBadgeVariants, tabsListVariants, tabsRootVariants, tabsTriggerVariants, textareaMessageVariants, textareaVariants, toast, toastVariants, toastViewportVariants, treeItemRowVariants, treeViewVariants, useOlunTheme, usePermission };
1695
+ export { ActionFooter, type ActionFooterAction, type ActionFooterProps, type ActionFooterStatus, Alert, type AlertEmphasis, type AlertProps, type AlertVariant, Avatar, AvatarFallback, type AvatarFallbackProps, AvatarImage, Badge, type BadgeProps, type BadgeTone, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, BulkActionBar, type BulkActionBarAction, type BulkActionBarProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardProse, CardTitle, type CardVariant, type CardVariantOptions, Checkbox, type CheckboxCheckedState, CheckboxGroup, type CheckboxGroupAppearance, type CheckboxGroupColumns, CheckboxGroupContext, type CheckboxGroupContextValue, type CheckboxGroupDensity, type CheckboxGroupOrientation, type CheckboxGroupProps, type CheckboxProps, type CheckboxSize, Chip, type ChipProps, type ChipSize, type ChipTone, type ChipVariant, ConfirmDialog, type ConfirmDialogProps, ContextMenu, type ContextMenuPosition, type ContextMenuProps, CopyButton, type CopyButtonProps, DataLayout, type DataLayoutProps, DataTable, type DataTableColumn, type DataTableLinkProps, type DataTableProps, type DataTableSort, type DataTableVirtualHandle, type DataTableVirtualOptions, type DataTableVirtualRange, DetailLayout, type DetailLayoutProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogEyebrow, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogRawContent, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, type EmptyStateSize, type EmptyStateTone, type EmptyStateVariantOptions, ErrorState, type ErrorStateProps, FileUploadZone, type FileUploadZoneProps, FilterToolbar, type FilterToolbarCollapseBelow, type FilterToolbarProps, FormField, type FormFieldProps, type FormFieldRenderProps, FormLayout, type FormLayoutProps, type FormLayoutSection, FormModal, type FormModalProps, IconButton, type IconButtonBadgeTone, type IconButtonProps, type IconButtonSize, type IconButtonVariant, InfoModal, type InfoModalProps, InlineAlert, type InlineAlertProps, type InlineAlertSurface, Input, type InputProps, type InputSize, type InputSizeLegacy, type InputState, Label, type LabelProps, ModeToggle, type ModeToggleOption, type ModeToggleProps, NotificationBadge, type NotificationBadgePlacement, type NotificationBadgeProps, type NotificationBadgeSize, OTPField, type OTPFieldProps, type OTPFieldSize, OlunLogo, OlunSymbol, type OlunTheme, type OlunThemeDuration, type OlunThemeState, OrganizationLogo, type OrganizationLogoId, type OrganizationLogoProps, PageHeader, type PageHeaderProps, PageSizeSelect, type PageSizeSelectProps, type PageSizeSelectSize, Pagination, type PaginationProps, type PaginationSize, PermissionContext, type PermissionEvaluator, type PermissionFallback, PermissionGuard, type PermissionGuardProps, PermissionProvider, type PermissionProviderProps, type PermissionScope, type PermissionState, Popover, PopoverAnchor, PopoverArrow, PopoverClose, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, Progress, type ProgressProps, type ProgressStatus, Radio, RadioGroup, type RadioGroupAppearance, type RadioGroupColumns, type RadioGroupDensity, type RadioGroupOrientation, type RadioGroupProps, type RadioProps, ScrollArea, ScrollBar, SearchField, type SearchFieldProps, type SearchFieldSize, Select, type SelectAppearance, type SelectOption, type SelectProps, type SelectSize, type SelectState, type SelectVariant, type SemanticRole, Separator, type SetOlunThemeOptions, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetDrawer, type SheetDrawerProps, SheetFooter, SheetHeader, type SheetMotionConfig, type SheetMotionDuration, type SheetMotionEasing, type SheetMotionType, SheetTitle, SheetTrigger, Skeleton, type SkeletonProps, SkeletonRow, type SkeletonRowColumn, type SkeletonRowProps, SkeletonText, type SkeletonTextProps, Spinner, type SpinnerProps, StatusBadge, type StatusBadgeEmphasis, type StatusBadgeProps, type StatusBadgeSize, type StatusBadgeStatus, type SurfaceLevel, Switch, type SwitchProps, type TabItem, Tabs, TabsContent, type TabsProps, type TabsVariant, Textarea, type TextareaProps, type TextareaSize, type TextareaSizeLegacy, type TextareaState, ThemeFab, type ThemeFabProps, ThemeToggle, Toast, type ToastAction, type ToastItem, type ToastOptions, ToastProvider, ToastRoot, type ToastVariant, ToastViewport, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type TreeItemRowVariantProps, type TreeItemState, type TreeNode, TreeView, type TreeViewProps, TwoTierBadge, type TwoTierBadgeEmphasis, type TwoTierBadgeProps, type TwoTierBadgeSize, type TwoTierBadgeTone, type UseOlunThemeValue, WizardLayout, type WizardLayoutProps, type WizardStep, type WizardStepState, actionFooterStatusVariants, actionFooterVariants, buttonVariants, cardVariants, checkboxBoxVariants, checkboxFieldVariants, checkboxGroupBoxVariants, checkboxGroupItemVariants, checkboxGroupVariants, checkboxRootVariants, checkboxVariants, chipCountVariants, chipVariants, cn, dataTableRowVariants, dataTableVariants, emptyStateIconVariants, emptyStateVariants, errorStateVariants, evaluatePermission, fileUploadIconVariants, fileUploadZoneVariants, formFieldControlStackClassName, formFieldDescriptionClassName, formFieldErrorClassName, formFieldLabelClassName, formFieldRequiredClassName, formFieldVariants, getOlunThemeState, getToastDuration, iconButtonBadgeVariants, iconButtonVariants, inputMessageVariants, inputVariants, limitToasts, modeToggleItemVariants, modeToggleVariants, notificationBadgeVariants, otpCellVariants, otpFieldGroupVariants, otpFieldMessageVariants, otpFieldVariants, paginationControlVariants, paginationVariants, radioControlVariants, radioGroupVariants, radioVariants, searchFieldInputVariants, searchFieldVariants, selectMessageVariants, selectVariants, setOlunTheme, skeletonVariants, spinnerVariants, tabsBadgeVariants, tabsListVariants, tabsRootVariants, tabsTriggerVariants, textareaMessageVariants, textareaVariants, toast, toastVariants, toastViewportVariants, treeItemRowVariants, treeViewVariants, useOlunTheme, usePermission };
package/dist/index.js CHANGED
@@ -5564,11 +5564,22 @@ var useIsomorphicLayoutEffect = typeof window === "undefined" ? React27.useEffec
5564
5564
  var VIRTUAL_DEFAULT_OVERSCAN = 8;
5565
5565
  var VIRTUAL_INITIAL_ROWS = 24;
5566
5566
  var VIRTUAL_FALLBACK_SIZE = { desktop: 48, mobile: 120 };
5567
+ function getScrollParent(node) {
5568
+ for (let el = node.parentElement; el && el !== document.body; el = el.parentElement) {
5569
+ const { overflowY } = window.getComputedStyle(el);
5570
+ if ((overflowY === "auto" || overflowY === "scroll") && el.scrollHeight > el.clientHeight) {
5571
+ return el;
5572
+ }
5573
+ }
5574
+ return null;
5575
+ }
5567
5576
  function useVirtualWindow({
5568
5577
  enabled,
5569
5578
  count,
5570
5579
  overscan,
5580
+ onRangeChange,
5571
5581
  desktopRef,
5582
+ headerRef,
5572
5583
  desktopListRef,
5573
5584
  mobileListRef
5574
5585
  }) {
@@ -5580,6 +5591,8 @@ function useVirtualWindow({
5580
5591
  });
5581
5592
  const measuredSize = React27.useRef({ desktop: 0, mobile: 0 });
5582
5593
  const update = React27.useRef(() => void 0);
5594
+ const reported = React27.useRef("");
5595
+ const latest = React27.useRef({ count, layout: "desktop" });
5583
5596
  update.current = () => {
5584
5597
  if (!enabled) {
5585
5598
  return;
@@ -5593,6 +5606,7 @@ function useVirtualWindow({
5593
5606
  measuredSize.current[layout] = itemHeight;
5594
5607
  }
5595
5608
  const size = measuredSize.current[layout] || VIRTUAL_FALLBACK_SIZE[layout];
5609
+ latest.current = { count, layout };
5596
5610
  let start = 0;
5597
5611
  let end = Math.min(count, VIRTUAL_INITIAL_ROWS);
5598
5612
  if (list) {
@@ -5600,6 +5614,23 @@ function useVirtualWindow({
5600
5614
  const viewport = window.innerHeight || document.documentElement.clientHeight;
5601
5615
  start = Math.min(count, Math.max(0, Math.floor(-top / size) - overscan));
5602
5616
  end = Math.min(count, Math.max(start, Math.ceil((viewport - top) / size) + overscan));
5617
+ if (onRangeChange) {
5618
+ const container = getScrollParent(list);
5619
+ const bounds = container?.getBoundingClientRect();
5620
+ let visibleTop = Math.max(0, bounds ? bounds.top : 0);
5621
+ const visibleBottom = Math.min(viewport, bounds ? bounds.bottom : viewport);
5622
+ const header = headerRef.current;
5623
+ if (layout === "desktop" && header) {
5624
+ visibleTop = Math.max(visibleTop, header.getBoundingClientRect().bottom);
5625
+ }
5626
+ const first = Math.min(count, Math.max(0, Math.floor((visibleTop - top) / size)));
5627
+ const last = Math.min(count, Math.max(first, Math.ceil((visibleBottom - top) / size)));
5628
+ const key = `${first}:${last}:${count}`;
5629
+ if (reported.current !== key) {
5630
+ reported.current = key;
5631
+ onRangeChange({ start: first, end: last });
5632
+ }
5633
+ }
5603
5634
  }
5604
5635
  setWin(
5605
5636
  (prev) => prev.layout === layout && prev.start === start && prev.end === end && prev.size === size ? prev : { layout, start, end, size }
@@ -5630,7 +5661,34 @@ function useVirtualWindow({
5630
5661
  window.cancelAnimationFrame(frame);
5631
5662
  };
5632
5663
  }, [enabled]);
5633
- return win;
5664
+ const scrollToIndex = React27.useCallback(
5665
+ (index) => {
5666
+ const { count: rowCount, layout } = latest.current;
5667
+ const list = (layout === "desktop" ? desktopListRef : mobileListRef).current;
5668
+ if (!list || rowCount === 0) {
5669
+ return;
5670
+ }
5671
+ const row = Math.min(rowCount - 1, Math.max(0, Math.floor(index)));
5672
+ const size = measuredSize.current[layout] || VIRTUAL_FALLBACK_SIZE[layout];
5673
+ const container = getScrollParent(list);
5674
+ let target = container ? container.getBoundingClientRect().top : 0;
5675
+ const header = headerRef.current;
5676
+ if (layout === "desktop" && header) {
5677
+ const { position, top } = window.getComputedStyle(header);
5678
+ if (position === "sticky") {
5679
+ target += (Number.parseFloat(top) || 0) + header.getBoundingClientRect().height;
5680
+ }
5681
+ }
5682
+ const delta = list.getBoundingClientRect().top + row * size - target;
5683
+ if (container) {
5684
+ container.scrollTop += delta;
5685
+ } else {
5686
+ window.scrollBy(0, delta);
5687
+ }
5688
+ },
5689
+ [desktopListRef, headerRef, mobileListRef]
5690
+ );
5691
+ return { win, scrollToIndex };
5634
5692
  }
5635
5693
  function DataTableInner({
5636
5694
  className,
@@ -5642,6 +5700,8 @@ function DataTableInner({
5642
5700
  selectable = false,
5643
5701
  selectedIds,
5644
5702
  onSelectionChange,
5703
+ selectionUnit = "\uAC1C",
5704
+ announceSelection = true,
5645
5705
  activeRowId,
5646
5706
  onRowContextMenu,
5647
5707
  sortBy,
@@ -5659,16 +5719,20 @@ function DataTableInner({
5659
5719
  const virtualOptions = virtual ? virtual === true ? {} : virtual : null;
5660
5720
  const isVirtual = virtualOptions !== null;
5661
5721
  const desktopRef = React27.useRef(null);
5722
+ const headerRef = React27.useRef(null);
5662
5723
  const desktopListRef = React27.useRef(null);
5663
5724
  const mobileListRef = React27.useRef(null);
5664
- const virtualWindow = useVirtualWindow({
5725
+ const { win: virtualWindow, scrollToIndex } = useVirtualWindow({
5665
5726
  enabled: isVirtual,
5666
5727
  count: data.length,
5667
5728
  overscan: virtualOptions?.overscan ?? VIRTUAL_DEFAULT_OVERSCAN,
5729
+ onRangeChange: virtualOptions?.onRangeChange,
5668
5730
  desktopRef,
5731
+ headerRef,
5669
5732
  desktopListRef,
5670
5733
  mobileListRef
5671
5734
  });
5735
+ React27.useImperativeHandle(virtualOptions?.handleRef, () => ({ scrollToIndex }), [scrollToIndex]);
5672
5736
  const resolvedSelectedIds = selectedIds ?? /* @__PURE__ */ new Set();
5673
5737
  const rowIds = data.map((row) => getRowId(row, keyField));
5674
5738
  const selectedCount = rowIds.filter((id) => resolvedSelectedIds.has(id)).length;
@@ -5773,13 +5837,13 @@ function DataTableInner({
5773
5837
  ),
5774
5838
  ...props,
5775
5839
  children: [
5776
- selectable ? /* @__PURE__ */ jsx31(
5840
+ selectable && announceSelection ? /* @__PURE__ */ jsx31(
5777
5841
  "div",
5778
5842
  {
5779
5843
  "data-slot": "data-table-selection-status",
5780
5844
  "aria-live": "polite",
5781
5845
  className: "sr-only",
5782
- children: selectedCount > 0 ? `${selectedCount.toLocaleString("ko-KR")}\uAC1C \uC120\uD0DD\uB428` : ""
5846
+ children: selectedCount > 0 ? `${selectedCount.toLocaleString("ko-KR")}${selectionUnit} \uC120\uD0DD\uB428` : ""
5783
5847
  }
5784
5848
  ) : null,
5785
5849
  loading && data.length > 0 ? /* @__PURE__ */ jsx31(
@@ -5801,6 +5865,7 @@ function DataTableInner({
5801
5865
  /* @__PURE__ */ jsxs30(
5802
5866
  "div",
5803
5867
  {
5868
+ ref: headerRef,
5804
5869
  "data-slot": "data-table-header",
5805
5870
  role: "row",
5806
5871
  className: cn(
@@ -6313,6 +6378,8 @@ function ClearButton({ onClear }) {
6313
6378
  );
6314
6379
  }
6315
6380
  var INLINE_HEIGHT = 40;
6381
+ var HIT_AREA = 44;
6382
+ var HIT_INSET = 8;
6316
6383
  var floatingStyle = {
6317
6384
  position: "sticky",
6318
6385
  bottom: "calc(var(--space-4) + env(safe-area-inset-bottom))",
@@ -6392,16 +6459,62 @@ function BulkActionBar({
6392
6459
  summary,
6393
6460
  compactSummary,
6394
6461
  idleContent,
6462
+ trailing,
6395
6463
  className,
6396
6464
  style,
6397
6465
  ...props
6398
6466
  }) {
6399
6467
  const inline = placement === "inline";
6468
+ const trailingSlot = trailing !== void 0 && trailing !== null ? /* @__PURE__ */ jsx34(
6469
+ "div",
6470
+ {
6471
+ "data-slot": "bulk-action-bar-trailing",
6472
+ style: {
6473
+ display: "flex",
6474
+ flexShrink: 0,
6475
+ alignItems: "center",
6476
+ gap: "var(--space-2)"
6477
+ },
6478
+ children: trailing
6479
+ }
6480
+ ) : null;
6400
6481
  const [summaryElement, setSummaryElement] = React28.useState(null);
6401
6482
  const compact = useCompactSummary(
6402
6483
  summaryElement,
6403
6484
  inline && compactSummary !== void 0 && compactSummary !== null
6404
6485
  );
6486
+ if (count === 0 && idleContent !== void 0 && trailingSlot) {
6487
+ return /* @__PURE__ */ jsxs33(
6488
+ "div",
6489
+ {
6490
+ "data-slot": "bulk-action-bar",
6491
+ "data-placement": placement,
6492
+ "data-state": "idle",
6493
+ className,
6494
+ style: { ...idleLineStyle, overflow: "visible", ...style },
6495
+ ...props,
6496
+ children: [
6497
+ /* @__PURE__ */ jsx34(
6498
+ "div",
6499
+ {
6500
+ role: "status",
6501
+ "data-slot": "bulk-action-bar-idle",
6502
+ style: {
6503
+ display: "flex",
6504
+ flex: "1 1 auto",
6505
+ minWidth: 0,
6506
+ alignItems: "center",
6507
+ columnGap: "var(--space-3)",
6508
+ overflow: "hidden"
6509
+ },
6510
+ children: idleContent
6511
+ }
6512
+ ),
6513
+ trailingSlot
6514
+ ]
6515
+ }
6516
+ );
6517
+ }
6405
6518
  if (count === 0 && idleContent !== void 0) {
6406
6519
  return /* @__PURE__ */ jsx34(
6407
6520
  "div",
@@ -6452,12 +6565,16 @@ function BulkActionBar({
6452
6565
  color: "var(--text-secondary)",
6453
6566
  ...inline ? (
6454
6567
  // inline-size containment: the summary never widens the band's parent. The
6455
- // slot is full-height with 3px side gutters so focus rings are not clipped.
6568
+ // slot clips text, so it is as tall as an IconButton's hit area (overhanging
6569
+ // the 40px band) and has that inset as its left gutter: a compact IconButton
6570
+ // keeps its full 44px target. The right gutter stays 3px (focus ring) so
6571
+ // clipped text keeps clear of the controls.
6456
6572
  {
6457
6573
  flex: "1 1 0",
6458
- alignSelf: "stretch",
6459
- margin: "0 -3px",
6460
- padding: "0 3px",
6574
+ alignSelf: "center",
6575
+ height: HIT_AREA,
6576
+ margin: `0 -3px 0 -${HIT_INSET}px`,
6577
+ padding: `0 3px 0 ${HIT_INSET}px`,
6461
6578
  overflow: "hidden",
6462
6579
  whiteSpace: "nowrap",
6463
6580
  contain: "inline-size"
@@ -6529,7 +6646,8 @@ function BulkActionBar({
6529
6646
  /* @__PURE__ */ jsx34(ClearButton, { onClear })
6530
6647
  ]
6531
6648
  }
6532
- )
6649
+ ),
6650
+ trailingSlot
6533
6651
  ]
6534
6652
  }
6535
6653
  );
@@ -6554,7 +6672,8 @@ function BulkActionBar({
6554
6672
  count > 0 && actions.length > 0 ? /* @__PURE__ */ jsx34(Divider, {}) : null,
6555
6673
  actionGroup,
6556
6674
  /* @__PURE__ */ jsx34(Divider, {}),
6557
- /* @__PURE__ */ jsx34(ClearButton, { onClear })
6675
+ /* @__PURE__ */ jsx34(ClearButton, { onClear }),
6676
+ trailingSlot
6558
6677
  ]
6559
6678
  }
6560
6679
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olundot/ui",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
4
4
  "description": "OLUN. shared React UI components built on OLUN design tokens",
5
5
  "license": "MIT",
6
6
  "keywords": [