@olundot/ui 0.20.0-next.12 → 0.20.0-next.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/CHANGELOG.md +31 -0
- package/dist/index.d.ts +13 -3
- package/dist/index.js +316 -73
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @olundot/ui
|
|
2
2
|
|
|
3
|
+
## 0.20.0-next.13
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 21aac35: `FilterToolbar`에 `layout`과 `appliedFilters`를 더했다.
|
|
8
|
+
|
|
9
|
+
- `layout="grid"`: 640px 이상에서 컨트롤 줄이 폭과 관계없이 한 줄이고 줄 폭을 다 채운다. 칸 비율은 칸 안 컨트롤 종류로 정한다. 검색 3, Select 2, 그 밖의 컨트롤(Combobox 등) 3, Chip과 접힌 필터 버튼, 보조 작업은 내용 폭이다. `filters`의 자식 하나가 칸 하나이고, 3개를 넘기면 개발 빌드에서 경고한다. 640px 이상에서 `collapsible`은 늘 접힌 필터 버튼 뒤에 있다. 640px 미만은 flow와 같다.
|
|
10
|
+
- `appliedFilters`: 640px 이상에서 툴바 아래에 고른 값을 지울 수 있는 Chip 줄로 보이고, `onClearFilters`가 있으면 끝에 "해제"를 둔다. 칩을 지우면 포커스가 다음 칩, 이전 칩, 접힌 필터 버튼 순으로 간다. 640px 미만은 지금처럼 적용 개수 줄이다. `activeFilterCount`를 주지 않으면 칩 개수를 쓴다. `layout`과 따로 쓴다.
|
|
11
|
+
- 기본값 `layout="flow"`와 `appliedFilters`가 없을 때의 출력은 그대로다.
|
|
12
|
+
- 타입 `FilterToolbarLayout`, `FilterToolbarAppliedFilter`를 내보낸다.
|
|
13
|
+
|
|
14
|
+
- 9b17d12: `ModeToggle`에 항목별 개수 `ModeToggleOption.count`를 추가했다. 라벨 뒤에 Tabs badge와 같은 개수 알약이 붙는다.
|
|
15
|
+
- 모양: 테두리가 없고, 채움은 `--action-selected` 반투명 겹침 하나라 바탕 위와 선택된 항목 위에서 모양이 같다. 숫자는 항목 글자색을 따르고 `tabular-nums`다. 높이 16px이라 항목 높이는 그대로다.
|
|
16
|
+
- 100부터 `99+`로 보인다. 0도 보인다. 숨기려면 값을 넘기지 않는다. 음수와 `NaN`은 보이지 않는다(개발 모드에서 경고).
|
|
17
|
+
- 항목 접근 이름에 실제 수가 들어간다. "오답 3"처럼 읽고, `99+`로 보이는 항목도 "전체 128"처럼 읽는다. 보이는 알약은 `aria-hidden`이다.
|
|
18
|
+
- `count`가 없으면 출력은 그대로다.
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 044b1c0: DataTable `rowActions` 우클릭 메뉴가 열린 채 창이 1024px 미만으로 줄어 카드로 바뀌면 메뉴를 닫는다.
|
|
23
|
+
|
|
24
|
+
- 항목은 실행하지 않는다. 포커스가 메뉴에 있었다면 그 행 카드의 행 메뉴 버튼으로 옮기고, 버튼이 없으면 카드로, 카드도 없으면 카드 목록으로 옮긴다. 포커스가 메뉴 밖이면 건드리지 않는다.
|
|
25
|
+
- `virtual` 표도 같다.
|
|
26
|
+
- 항목을 고른 직후 카드로 바뀌면 그 항목은 한 번 실행하고, 포커스는 그 카드의 행 메뉴 버튼으로 돌아간다.
|
|
27
|
+
|
|
28
|
+
- 30fd979: `--olun-bulk-bar-offset` 값이 화면 아래 끝에서 떠 있는 `BulkActionBar` 카드 위 끝까지의 거리(px)가 된다. 이름은 그대로다.
|
|
29
|
+
- 카드가 화면 아래 16px에 붙은 보통 경우는 예전 값(카드 높이 + `16px + env(safe-area-inset-bottom)`)과 같다.
|
|
30
|
+
- 목록 끝에서 카드가 페이지 푸터 위로 밀려 올라가도 값이 따라간다. 스크롤(문서와 스크롤 조상), 창 크기, 카드 크기가 바뀌거나 다른 이유로 카드가 화면에서 움직이면 다음 프레임에 다시 잰다. 그래서 `ToastViewport`가 카드 윗부분을 덮지 않는다.
|
|
31
|
+
- 카드 아래 끝이 화면 아래 끝에서 204px보다 높으면(짧은 목록이나 화면 밖) 값을 두지 않는다. 한 줄 토스트 3개가 아래 24px 자리에서 카드 밑에 들어간다.
|
|
32
|
+
- 값을 `calc(var(--olun-bulk-bar-offset, 0px) + …)`로 읽는 소비자 토스트는 고치지 않아도 된다.
|
|
33
|
+
|
|
3
34
|
## 0.20.0-next.12
|
|
4
35
|
|
|
5
36
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -857,6 +857,12 @@ interface InfoModalProps {
|
|
|
857
857
|
declare function InfoModal({ open, onOpenChange, title, description, children, closeLabel, footer, }: InfoModalProps): react_jsx_runtime.JSX.Element;
|
|
858
858
|
|
|
859
859
|
type FilterToolbarCollapseBelow = "sm" | "md" | "lg" | "never";
|
|
860
|
+
type FilterToolbarLayout = "flow" | "grid";
|
|
861
|
+
interface FilterToolbarAppliedFilter {
|
|
862
|
+
key: string;
|
|
863
|
+
label: string;
|
|
864
|
+
onRemove: () => void;
|
|
865
|
+
}
|
|
860
866
|
interface FilterToolbarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
861
867
|
search?: React.ReactNode;
|
|
862
868
|
filters?: React.ReactNode;
|
|
@@ -868,6 +874,8 @@ interface FilterToolbarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
868
874
|
resultSummary?: React.ReactNode;
|
|
869
875
|
clearAction?: React.ReactNode;
|
|
870
876
|
actions?: React.ReactNode;
|
|
877
|
+
layout?: FilterToolbarLayout;
|
|
878
|
+
appliedFilters?: FilterToolbarAppliedFilter[];
|
|
871
879
|
}
|
|
872
880
|
declare const FilterToolbar: React.ForwardRefExoticComponent<FilterToolbarProps & React.RefAttributes<HTMLDivElement>>;
|
|
873
881
|
|
|
@@ -1292,8 +1300,8 @@ type BulkActionBarProps = BulkActionBarBaseProps & ({
|
|
|
1292
1300
|
* with the clear (✕) button on its right, `summary` under it at full width, then
|
|
1293
1301
|
* the actions as outline sm Buttons aligned right, wrapping onto more lines when
|
|
1294
1302
|
* they do not fit. `variant: "destructive"` is outline danger. The card is
|
|
1295
|
-
* min(360px, its slot − 32px) wide; while it is
|
|
1296
|
-
* `--olun-bulk-bar-offset` (
|
|
1303
|
+
* min(360px, its slot − 32px) wide; while it is near the viewport bottom the document root
|
|
1304
|
+
* carries `--olun-bulk-bar-offset` (viewport bottom → card top) for toasts to clear it.
|
|
1297
1305
|
* DOM order stays count → actions → ✕. It takes no `trailing`.
|
|
1298
1306
|
*
|
|
1299
1307
|
* placement="inline" (deprecated) is a top-sticky band that replaces the status
|
|
@@ -1966,6 +1974,8 @@ interface ModeToggleOption<T extends string> {
|
|
|
1966
1974
|
value: T;
|
|
1967
1975
|
label: string;
|
|
1968
1976
|
icon?: LucideIcon;
|
|
1977
|
+
/** 라벨 뒤 개수 알약입니다. 0 이상의 정수만 보이고, 100부터는 `99+`로 보입니다. 접근 이름에는 실제 수가 들어갑니다. */
|
|
1978
|
+
count?: number;
|
|
1969
1979
|
disabled?: boolean;
|
|
1970
1980
|
}
|
|
1971
1981
|
interface ModeToggleProps<T extends string> extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
@@ -2335,4 +2345,4 @@ interface OrganizationLogoProps extends Omit<SVGProps<SVGSVGElement>, "width" |
|
|
|
2335
2345
|
}
|
|
2336
2346
|
declare function OrganizationLogo({ organization, size, className, style, role, "aria-label": ariaLabel, "aria-hidden": ariaHidden, ...props }: OrganizationLogoProps): react_jsx_runtime.JSX.Element;
|
|
2337
2347
|
|
|
2338
|
-
export { ActionFooter, type ActionFooterAction, type ActionFooterProps, type ActionFooterStatus, ActionMenu, type ActionMenuGroup, type ActionMenuItem, type ActionMenuProps, ActionSheet, type ActionSheetIconProps, type ActionSheetItem, type ActionSheetProps, Alert, AlertDialog, type AlertDialogProps, type AlertDialogTone, type AlertEmphasis, type AlertMarker, 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, 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 DataTableMobileCardContent, type DataTableMobileMetaLine, type DataTableProps, type DataTableRowActions, type DataTableSort, type DataTableVirtualHandle, type DataTableVirtualOptions, type DataTableVirtualRange, DetailLayout, type DetailLayoutProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogEyebrow, DialogFooter, DialogHeader, type DialogMobilePresentation, DialogOverlay, DialogPortal, type DialogProps, DialogRawContent, type DialogSize, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateLayout, 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, InfoModal, type InfoModalProps, InlineAlert, type InlineAlertProps, Input, type InputProps, type InputSize, type InputSizeLegacy, type InputState, Label, type LabelProps, ListCard, type ListCardActions, type ListCardProps, 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, type OverlayScrim, 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, type SheetProps, type SheetSize, 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, StatusDot, type StatusDotProps, type StatusDotTone, type SurfaceLevel, Switch, type SwitchProps, TABLE_PAGE_SIZE_OPTIONS, type TabItem, TablePagination, type TablePaginationProps, type TablePaginationVisibility, 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, shouldHideTablePagination, skeletonVariants, spinnerVariants, tabsBadgeVariants, tabsListVariants, tabsRootVariants, tabsTriggerVariants, textareaMessageVariants, textareaVariants, toast, toastVariants, toastViewportVariants, treeItemRowVariants, treeViewVariants, useOlunTheme, usePermission };
|
|
2348
|
+
export { ActionFooter, type ActionFooterAction, type ActionFooterProps, type ActionFooterStatus, ActionMenu, type ActionMenuGroup, type ActionMenuItem, type ActionMenuProps, ActionSheet, type ActionSheetIconProps, type ActionSheetItem, type ActionSheetProps, Alert, AlertDialog, type AlertDialogProps, type AlertDialogTone, type AlertEmphasis, type AlertMarker, 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, 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 DataTableMobileCardContent, type DataTableMobileMetaLine, type DataTableProps, type DataTableRowActions, type DataTableSort, type DataTableVirtualHandle, type DataTableVirtualOptions, type DataTableVirtualRange, DetailLayout, type DetailLayoutProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogEyebrow, DialogFooter, DialogHeader, type DialogMobilePresentation, DialogOverlay, DialogPortal, type DialogProps, DialogRawContent, type DialogSize, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateLayout, type EmptyStateProps, type EmptyStateSize, type EmptyStateTone, type EmptyStateVariantOptions, ErrorState, type ErrorStateProps, FileUploadZone, type FileUploadZoneProps, FilterToolbar, type FilterToolbarAppliedFilter, type FilterToolbarCollapseBelow, type FilterToolbarLayout, type FilterToolbarProps, FormField, type FormFieldProps, type FormFieldRenderProps, FormLayout, type FormLayoutProps, type FormLayoutSection, FormModal, type FormModalProps, IconButton, type IconButtonBadgeTone, type IconButtonProps, type IconButtonSize, InfoModal, type InfoModalProps, InlineAlert, type InlineAlertProps, Input, type InputProps, type InputSize, type InputSizeLegacy, type InputState, Label, type LabelProps, ListCard, type ListCardActions, type ListCardProps, 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, type OverlayScrim, 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, type SheetProps, type SheetSize, 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, StatusDot, type StatusDotProps, type StatusDotTone, type SurfaceLevel, Switch, type SwitchProps, TABLE_PAGE_SIZE_OPTIONS, type TabItem, TablePagination, type TablePaginationProps, type TablePaginationVisibility, 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, shouldHideTablePagination, skeletonVariants, spinnerVariants, tabsBadgeVariants, tabsListVariants, tabsRootVariants, tabsTriggerVariants, textareaMessageVariants, textareaVariants, toast, toastVariants, toastViewportVariants, treeItemRowVariants, treeViewVariants, useOlunTheme, usePermission };
|
package/dist/index.js
CHANGED
|
@@ -5547,7 +5547,7 @@ var PopoverArrow = React30.forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
5547
5547
|
PopoverArrow.displayName = PopoverPrimitive.Arrow.displayName;
|
|
5548
5548
|
|
|
5549
5549
|
// src/components/ui/filter-toolbar.tsx
|
|
5550
|
-
import { Fragment as
|
|
5550
|
+
import { Fragment as Fragment14, jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
5551
5551
|
var collapsibleClassNames = {
|
|
5552
5552
|
sm: {
|
|
5553
5553
|
inline: "hidden @[640px]:flex",
|
|
@@ -5566,6 +5566,41 @@ var collapsibleClassNames = {
|
|
|
5566
5566
|
trigger: "hidden"
|
|
5567
5567
|
}
|
|
5568
5568
|
};
|
|
5569
|
+
var gridCollapsibleClassNames = {
|
|
5570
|
+
sm: { inline: "hidden", trigger: "" },
|
|
5571
|
+
md: { inline: "hidden", trigger: "" },
|
|
5572
|
+
lg: { inline: "hidden", trigger: "" },
|
|
5573
|
+
never: { inline: "flex @[640px]:hidden", trigger: "hidden @[640px]:inline" }
|
|
5574
|
+
};
|
|
5575
|
+
var gridSearchClassName = "order-1 min-w-[min(160px,100%)] max-w-full flex-[1_1_0%] @[640px]:min-w-0 @[640px]:flex-[3_1_0%]";
|
|
5576
|
+
var gridFiltersClassName = "order-3 flex min-w-0 flex-[1_0_100%] flex-wrap items-center gap-[var(--space-2)] @[640px]:contents";
|
|
5577
|
+
var gridCellClassName = cn(
|
|
5578
|
+
"contents @[640px]:block @[640px]:order-3 @[640px]:min-w-0 @[640px]:flex-[3_1_0%]",
|
|
5579
|
+
"@[640px]:[&:has([data-slot=select-trigger])]:flex-[2_1_0%]",
|
|
5580
|
+
"@[640px]:[&:has(>[data-slot=chip])]:flex-none",
|
|
5581
|
+
// A Chip group is named: a role="group" child that holds the Chips. A control that shows its
|
|
5582
|
+
// values as Chips keeps the default share.
|
|
5583
|
+
"@[640px]:[&:has(>[role=group]>[data-slot=chip])]:flex-none",
|
|
5584
|
+
// The control fills its cell, through a width the consumer put on a wrapper.
|
|
5585
|
+
"@[640px]:[&>:not([data-slot=chip])]:w-full @[640px]:[&_[data-slot=select-trigger]]:w-full"
|
|
5586
|
+
);
|
|
5587
|
+
var MAX_GRID_FILTERS = 3;
|
|
5588
|
+
var focusableSelector = "input, button, [tabindex]:not([tabindex='-1'])";
|
|
5589
|
+
function canTakeFocus(element) {
|
|
5590
|
+
return Boolean(element && element.getClientRects().length > 0 && !element.matches(":disabled"));
|
|
5591
|
+
}
|
|
5592
|
+
function filterCells(node, prefix = "") {
|
|
5593
|
+
return React31.Children.toArray(node).flatMap((child, index) => {
|
|
5594
|
+
const key = `${prefix}${React31.isValidElement(child) ? child.key : index}`;
|
|
5595
|
+
return React31.isValidElement(child) && child.type === React31.Fragment ? filterCells(child.props.children, `${key}/`) : [{ key, cell: child }];
|
|
5596
|
+
});
|
|
5597
|
+
}
|
|
5598
|
+
function warnGridFilters(count) {
|
|
5599
|
+
if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
|
|
5600
|
+
console.warn(
|
|
5601
|
+
`FilterToolbar: layout="grid" fits ${MAX_GRID_FILTERS} filters on the line, got ${count}. Move the rest to \`collapsible\`.`
|
|
5602
|
+
);
|
|
5603
|
+
}
|
|
5569
5604
|
var FilterToolbar = React31.forwardRef(
|
|
5570
5605
|
({
|
|
5571
5606
|
className,
|
|
@@ -5573,12 +5608,14 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5573
5608
|
filters,
|
|
5574
5609
|
collapsible,
|
|
5575
5610
|
collapseBelow = "lg",
|
|
5576
|
-
activeFilterCount
|
|
5611
|
+
activeFilterCount: activeFilterCountProp,
|
|
5577
5612
|
onClearFilters,
|
|
5578
5613
|
collapsedLabel = "\uD544\uD130",
|
|
5579
5614
|
resultSummary,
|
|
5580
5615
|
clearAction,
|
|
5581
5616
|
actions,
|
|
5617
|
+
layout = "flow",
|
|
5618
|
+
appliedFilters,
|
|
5582
5619
|
...props
|
|
5583
5620
|
}, ref) => {
|
|
5584
5621
|
const [rootElement, setRootElement] = React31.useState(
|
|
@@ -5589,6 +5626,10 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5589
5626
|
);
|
|
5590
5627
|
const [overlayOpen, setOverlayOpen] = React31.useState(false);
|
|
5591
5628
|
const triggerRef = React31.useRef(null);
|
|
5629
|
+
const rowRef = React31.useRef(null);
|
|
5630
|
+
const chipsRef = React31.useRef(null);
|
|
5631
|
+
const chipRemoveRefs = React31.useRef(/* @__PURE__ */ new Map());
|
|
5632
|
+
const pendingFocusRef = React31.useRef(null);
|
|
5592
5633
|
const setRootRefs = React31.useCallback(
|
|
5593
5634
|
(element) => {
|
|
5594
5635
|
setRootElement(element);
|
|
@@ -5612,13 +5653,49 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5612
5653
|
setOverlayOpen(open);
|
|
5613
5654
|
if (!open) queueMicrotask(() => triggerRef.current?.focus());
|
|
5614
5655
|
}, []);
|
|
5656
|
+
const isGrid = layout === "grid";
|
|
5657
|
+
const gridCells = isGrid ? filterCells(filters) : [];
|
|
5658
|
+
const filterCellCount = gridCells.length;
|
|
5659
|
+
React31.useEffect(() => {
|
|
5660
|
+
if (filterCellCount > MAX_GRID_FILTERS) warnGridFilters(filterCellCount);
|
|
5661
|
+
}, [filterCellCount]);
|
|
5662
|
+
React31.useEffect(() => {
|
|
5663
|
+
const ownerDocument = rootElement?.ownerDocument;
|
|
5664
|
+
if (!ownerDocument) return;
|
|
5665
|
+
const dropOutside = (event) => {
|
|
5666
|
+
if (!chipsRef.current?.contains(event.target)) pendingFocusRef.current = null;
|
|
5667
|
+
};
|
|
5668
|
+
ownerDocument.addEventListener("focusin", dropOutside);
|
|
5669
|
+
ownerDocument.addEventListener("pointerdown", dropOutside, true);
|
|
5670
|
+
return () => {
|
|
5671
|
+
ownerDocument.removeEventListener("focusin", dropOutside);
|
|
5672
|
+
ownerDocument.removeEventListener("pointerdown", dropOutside, true);
|
|
5673
|
+
};
|
|
5674
|
+
}, [rootElement]);
|
|
5675
|
+
React31.useEffect(() => {
|
|
5676
|
+
const request = pendingFocusRef.current;
|
|
5677
|
+
if (!request) return;
|
|
5678
|
+
const present = new Set(appliedFilters?.map((filter) => filter.key));
|
|
5679
|
+
if (request.removed.some((key) => present.has(key))) return;
|
|
5680
|
+
pendingFocusRef.current = null;
|
|
5681
|
+
const active = rootElement?.ownerDocument.activeElement;
|
|
5682
|
+
if (active && active !== rootElement.ownerDocument.body) return;
|
|
5683
|
+
const candidates = [
|
|
5684
|
+
...request.next.map((key) => chipRemoveRefs.current.get(key)),
|
|
5685
|
+
triggerRef.current,
|
|
5686
|
+
...rowRef.current?.querySelectorAll(focusableSelector) ?? []
|
|
5687
|
+
];
|
|
5688
|
+
candidates.find(canTakeFocus)?.focus();
|
|
5689
|
+
}, [appliedFilters, rootElement]);
|
|
5615
5690
|
const hasControls = Boolean(search || filters || collapsible);
|
|
5616
5691
|
const hasMeta = Boolean(
|
|
5617
5692
|
resultSummary || clearAction || actions && !hasControls
|
|
5618
5693
|
);
|
|
5694
|
+
const activeFilterCount = activeFilterCountProp ?? appliedFilters?.length ?? 0;
|
|
5619
5695
|
const hasAppliedFilters = activeFilterCount > 0;
|
|
5696
|
+
const hasAppliedChips = Boolean(appliedFilters && appliedFilters.length > 0);
|
|
5620
5697
|
const usesSheet = containerWidth !== null && containerWidth < 640;
|
|
5621
|
-
const collapseClasses = collapsibleClassNames[collapseBelow];
|
|
5698
|
+
const collapseClasses = (isGrid ? gridCollapsibleClassNames : collapsibleClassNames)[collapseBelow];
|
|
5622
5699
|
const collapseTriggerLabel = hasAppliedFilters ? `${collapsedLabel}, ${activeFilterCount}\uAC1C \uC801\uC6A9` : collapsedLabel;
|
|
5623
5700
|
const clearFiltersButton = onClearFilters ? /* @__PURE__ */ jsx32(
|
|
5624
5701
|
"button",
|
|
@@ -5689,14 +5766,18 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5689
5766
|
hasControls ? /* @__PURE__ */ jsxs28(
|
|
5690
5767
|
"div",
|
|
5691
5768
|
{
|
|
5769
|
+
ref: rowRef,
|
|
5692
5770
|
"data-slot": "filter-toolbar-row",
|
|
5693
|
-
className:
|
|
5771
|
+
className: cn(
|
|
5772
|
+
"flex min-h-[32px] w-full flex-wrap items-center justify-start gap-x-[var(--space-2)] gap-y-[var(--space-2)]",
|
|
5773
|
+
isGrid && "@[640px]:flex-nowrap"
|
|
5774
|
+
),
|
|
5694
5775
|
children: [
|
|
5695
5776
|
search ? /* @__PURE__ */ jsx32(
|
|
5696
5777
|
"div",
|
|
5697
5778
|
{
|
|
5698
5779
|
"data-slot": "filter-toolbar-search",
|
|
5699
|
-
className: "order-1 min-w-[min(160px,100%)] max-w-full flex-[1_1_0%] @[640px]:min-w-0 @[640px]:flex-[1_1_280px]",
|
|
5780
|
+
className: isGrid ? gridSearchClassName : "order-1 min-w-[min(160px,100%)] max-w-full flex-[1_1_0%] @[640px]:min-w-0 @[640px]:flex-[1_1_280px]",
|
|
5700
5781
|
children: search
|
|
5701
5782
|
}
|
|
5702
5783
|
) : null,
|
|
@@ -5723,8 +5804,16 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5723
5804
|
"div",
|
|
5724
5805
|
{
|
|
5725
5806
|
"data-slot": "filter-toolbar-filters",
|
|
5726
|
-
className: "order-3 flex min-w-0 flex-[1_0_100%] flex-wrap items-center gap-[var(--space-2)] @[640px]:flex-[2_1_auto]",
|
|
5727
|
-
children:
|
|
5807
|
+
className: isGrid ? gridFiltersClassName : "order-3 flex min-w-0 flex-[1_0_100%] flex-wrap items-center gap-[var(--space-2)] @[640px]:flex-[2_1_auto]",
|
|
5808
|
+
children: isGrid ? gridCells.map(({ key, cell }) => /* @__PURE__ */ jsx32(
|
|
5809
|
+
"div",
|
|
5810
|
+
{
|
|
5811
|
+
"data-slot": "filter-toolbar-cell",
|
|
5812
|
+
className: gridCellClassName,
|
|
5813
|
+
children: cell
|
|
5814
|
+
},
|
|
5815
|
+
key
|
|
5816
|
+
)) : filters
|
|
5728
5817
|
}
|
|
5729
5818
|
) : null,
|
|
5730
5819
|
collapsible && !overlayOpen ? /* @__PURE__ */ jsx32(
|
|
@@ -5759,18 +5848,72 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5759
5848
|
children: collapsedContent
|
|
5760
5849
|
}
|
|
5761
5850
|
) : null,
|
|
5851
|
+
hasAppliedChips ? /* @__PURE__ */ jsxs28(
|
|
5852
|
+
"div",
|
|
5853
|
+
{
|
|
5854
|
+
ref: chipsRef,
|
|
5855
|
+
role: "group",
|
|
5856
|
+
"aria-label": collapsedLabel,
|
|
5857
|
+
"data-slot": "filter-toolbar-applied-chips",
|
|
5858
|
+
className: "hidden flex-wrap items-center gap-[var(--space-2)] @[640px]:flex",
|
|
5859
|
+
children: [
|
|
5860
|
+
appliedFilters.map((filter, index) => /* @__PURE__ */ jsx32(
|
|
5861
|
+
Chip,
|
|
5862
|
+
{
|
|
5863
|
+
ref: (button) => {
|
|
5864
|
+
if (button) chipRemoveRefs.current.set(filter.key, button);
|
|
5865
|
+
else chipRemoveRefs.current.delete(filter.key);
|
|
5866
|
+
},
|
|
5867
|
+
variant: "removable",
|
|
5868
|
+
size: "md",
|
|
5869
|
+
removeLabel: `${filter.label} \uC81C\uAC70`,
|
|
5870
|
+
onClick: () => {
|
|
5871
|
+
pendingFocusRef.current = {
|
|
5872
|
+
removed: [filter.key],
|
|
5873
|
+
next: [appliedFilters[index + 1]?.key, appliedFilters[index - 1]?.key].filter(
|
|
5874
|
+
(key) => key !== void 0
|
|
5875
|
+
)
|
|
5876
|
+
};
|
|
5877
|
+
filter.onRemove();
|
|
5878
|
+
},
|
|
5879
|
+
children: filter.label
|
|
5880
|
+
},
|
|
5881
|
+
filter.key
|
|
5882
|
+
)),
|
|
5883
|
+
onClearFilters ? /* @__PURE__ */ jsx32(
|
|
5884
|
+
"button",
|
|
5885
|
+
{
|
|
5886
|
+
type: "button",
|
|
5887
|
+
"data-slot": "filter-toolbar-clear-filters",
|
|
5888
|
+
className: "cursor-pointer border-0 bg-transparent p-0 text-body-sm font-medium text-text-secondary no-underline",
|
|
5889
|
+
onClick: () => {
|
|
5890
|
+
pendingFocusRef.current = {
|
|
5891
|
+
removed: appliedFilters.map((filter) => filter.key),
|
|
5892
|
+
next: []
|
|
5893
|
+
};
|
|
5894
|
+
onClearFilters();
|
|
5895
|
+
},
|
|
5896
|
+
children: "\uD574\uC81C"
|
|
5897
|
+
}
|
|
5898
|
+
) : null
|
|
5899
|
+
]
|
|
5900
|
+
}
|
|
5901
|
+
) : null,
|
|
5762
5902
|
hasAppliedFilters ? /* @__PURE__ */ jsxs28(
|
|
5763
5903
|
"div",
|
|
5764
5904
|
{
|
|
5765
5905
|
"data-slot": "filter-toolbar-applied",
|
|
5766
|
-
className:
|
|
5906
|
+
className: cn(
|
|
5907
|
+
"flex items-center gap-[var(--space-1)] text-[11px] text-text-tertiary",
|
|
5908
|
+
hasAppliedChips && "@[640px]:hidden"
|
|
5909
|
+
),
|
|
5767
5910
|
children: [
|
|
5768
5911
|
/* @__PURE__ */ jsxs28("span", { children: [
|
|
5769
5912
|
"\uD544\uD130 ",
|
|
5770
5913
|
activeFilterCount,
|
|
5771
5914
|
"\uAC1C \uC801\uC6A9"
|
|
5772
5915
|
] }),
|
|
5773
|
-
onClearFilters ? /* @__PURE__ */ jsxs28(
|
|
5916
|
+
onClearFilters ? /* @__PURE__ */ jsxs28(Fragment14, { children: [
|
|
5774
5917
|
/* @__PURE__ */ jsx32("span", { "aria-hidden": "true", children: " \xB7 " }),
|
|
5775
5918
|
/* @__PURE__ */ jsx32(
|
|
5776
5919
|
"button",
|
|
@@ -6078,7 +6221,7 @@ function DropdownMenuSubContent({
|
|
|
6078
6221
|
}
|
|
6079
6222
|
|
|
6080
6223
|
// src/components/ui/action-menu.tsx
|
|
6081
|
-
import { Fragment as
|
|
6224
|
+
import { Fragment as Fragment16, jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
6082
6225
|
var sheetRowClassName = cn(
|
|
6083
6226
|
"group flex min-h-12 w-full cursor-pointer items-center gap-[var(--space-3)] px-[var(--space-4)] py-[var(--space-2)] text-left",
|
|
6084
6227
|
"border-t border-[var(--border-subtle)] text-[13px] font-medium leading-normal text-text-primary",
|
|
@@ -6181,10 +6324,10 @@ function ActionMenuSheet({
|
|
|
6181
6324
|
},
|
|
6182
6325
|
children: [
|
|
6183
6326
|
Icon ? /* @__PURE__ */ jsx34(Icon, { "aria-hidden": true, size: 17, strokeWidth: 1.75, className: cn("shrink-0", reason && unavailableClassName) }) : null,
|
|
6184
|
-
/* @__PURE__ */ jsx34("span", { className: "min-w-0 flex-1 break-keep", children: reason ? /* @__PURE__ */ jsxs30(
|
|
6327
|
+
/* @__PURE__ */ jsx34("span", { className: "min-w-0 flex-1 break-keep", children: reason ? /* @__PURE__ */ jsxs30(Fragment16, { children: [
|
|
6185
6328
|
/* @__PURE__ */ jsx34("span", { id: itemLabelId, className: unavailableClassName, children: item.label }),
|
|
6186
6329
|
/* @__PURE__ */ jsx34("span", { id: reasonId, className: reasonClassName, children: reason })
|
|
6187
|
-
] }) : /* @__PURE__ */ jsxs30(
|
|
6330
|
+
] }) : /* @__PURE__ */ jsxs30(Fragment16, { children: [
|
|
6188
6331
|
item.label,
|
|
6189
6332
|
item.description ? /* @__PURE__ */ jsx34("span", { className: sheetRowDescriptionClassName, children: item.description }) : null
|
|
6190
6333
|
] }) })
|
|
@@ -6292,7 +6435,7 @@ function ActionMenu({
|
|
|
6292
6435
|
triggerRef.current?.focus();
|
|
6293
6436
|
};
|
|
6294
6437
|
const triggerLabel = trigger.props["aria-label"];
|
|
6295
|
-
return /* @__PURE__ */ jsxs30(
|
|
6438
|
+
return /* @__PURE__ */ jsxs30(Fragment16, { children: [
|
|
6296
6439
|
/* @__PURE__ */ jsxs30(DropdownMenu, { open: open && presentation === "dropdown", onOpenChange: setOpen, children: [
|
|
6297
6440
|
/* @__PURE__ */ jsx34(DropdownMenuTrigger, { asChild: true, "aria-expanded": open, children: /* @__PURE__ */ jsx34(Slot3.Root, { ref: triggerRef, children: trigger }) }),
|
|
6298
6441
|
/* @__PURE__ */ jsx34(DropdownMenuContent, { align: "end", onCloseAutoFocus: handleDropdownCloseAutoFocus, children: menuGroups.map((group, index) => /* @__PURE__ */ jsxs30(React32.Fragment, { children: [
|
|
@@ -6704,7 +6847,7 @@ function ContextMenu({
|
|
|
6704
6847
|
// src/components/ui/list-card.tsx
|
|
6705
6848
|
import * as React34 from "react";
|
|
6706
6849
|
import { ChevronRight as ChevronRight2, MoreVertical } from "lucide-react";
|
|
6707
|
-
import { Fragment as
|
|
6850
|
+
import { Fragment as Fragment17, jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
6708
6851
|
function lineTokens(value) {
|
|
6709
6852
|
return React34.Children.toArray(value).filter((token) => token !== "");
|
|
6710
6853
|
}
|
|
@@ -6791,7 +6934,7 @@ function ListCard({
|
|
|
6791
6934
|
children: overlay && href != null ? React34.createElement(linkComponent ?? "a", { ...linkProps, href, className: overlayClassName }, title) : title
|
|
6792
6935
|
}
|
|
6793
6936
|
);
|
|
6794
|
-
const content = /* @__PURE__ */ jsxs33(
|
|
6937
|
+
const content = /* @__PURE__ */ jsxs33(Fragment17, { children: [
|
|
6795
6938
|
leading != null ? /* @__PURE__ */ jsx37("span", { className: "flex min-h-[18px] items-center", children: leading }) : null,
|
|
6796
6939
|
/* @__PURE__ */ jsxs33("span", { className: "min-w-0", children: [
|
|
6797
6940
|
overlay && href == null ? (
|
|
@@ -6822,7 +6965,7 @@ function ListCard({
|
|
|
6822
6965
|
),
|
|
6823
6966
|
children: [
|
|
6824
6967
|
hasValue ? /* @__PURE__ */ jsx37("span", { "data-slot": `${slot}-value`, className: "text-[13px] leading-[20px] text-text-secondary tabular-nums", children: value }) : null,
|
|
6825
|
-
actions != null ? /* @__PURE__ */ jsx37("span", { className: "relative z-[1] flex", children: /* @__PURE__ */ jsx37(
|
|
6968
|
+
actions != null ? /* @__PURE__ */ jsx37("span", { "data-slot": `${slot}-actions`, className: "relative z-[1] flex", children: /* @__PURE__ */ jsx37(
|
|
6826
6969
|
ActionMenu,
|
|
6827
6970
|
{
|
|
6828
6971
|
title: typeof title === "string" ? title : void 0,
|
|
@@ -6856,7 +6999,7 @@ function ListCard({
|
|
|
6856
6999
|
}
|
|
6857
7000
|
|
|
6858
7001
|
// src/components/ui/data-table.tsx
|
|
6859
|
-
import { Fragment as
|
|
7002
|
+
import { Fragment as Fragment19, jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
6860
7003
|
var dataTableVariants = cva13(
|
|
6861
7004
|
[
|
|
6862
7005
|
"relative overflow-hidden rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
|
|
@@ -6979,25 +7122,24 @@ function RowActionsCell({
|
|
|
6979
7122
|
);
|
|
6980
7123
|
}
|
|
6981
7124
|
function RowContextMenu({
|
|
6982
|
-
|
|
7125
|
+
menuKey,
|
|
6983
7126
|
position,
|
|
6984
7127
|
groups,
|
|
7128
|
+
cards,
|
|
6985
7129
|
onClose
|
|
6986
7130
|
}) {
|
|
6987
|
-
const [open, setOpen] = React35.useState(
|
|
6988
|
-
const
|
|
6989
|
-
const
|
|
7131
|
+
const [open, setOpen] = React35.useState(true);
|
|
7132
|
+
const closeRef = React35.useRef(null);
|
|
7133
|
+
const pressedOutside = React35.useRef(false);
|
|
7134
|
+
const close = (reason) => {
|
|
7135
|
+
closeRef.current ??= reason;
|
|
7136
|
+
setOpen(false);
|
|
7137
|
+
};
|
|
6990
7138
|
const shownGroups = React35.useRef([]);
|
|
6991
7139
|
if (groups) shownGroups.current = groups;
|
|
6992
|
-
const gone =
|
|
7140
|
+
const gone = groups === null;
|
|
6993
7141
|
const contentRef = React35.useRef(null);
|
|
6994
7142
|
const focusInsideRef = React35.useRef(false);
|
|
6995
|
-
React35.useEffect(() => {
|
|
6996
|
-
pendingRef.current = null;
|
|
6997
|
-
outsideRef.current = false;
|
|
6998
|
-
focusInsideRef.current = false;
|
|
6999
|
-
setOpen(openKey !== null);
|
|
7000
|
-
}, [openKey]);
|
|
7001
7143
|
useIsomorphicLayoutEffect(() => {
|
|
7002
7144
|
const content = contentRef.current;
|
|
7003
7145
|
if (!open || !focusInsideRef.current || !content?.isConnected) return;
|
|
@@ -7007,13 +7149,20 @@ function RowContextMenu({
|
|
|
7007
7149
|
next.focus();
|
|
7008
7150
|
});
|
|
7009
7151
|
React35.useEffect(() => {
|
|
7010
|
-
if (gone)
|
|
7152
|
+
if (gone) close({ by: "dismiss", outside: false });
|
|
7011
7153
|
}, [gone]);
|
|
7154
|
+
useIsomorphicLayoutEffect(() => {
|
|
7155
|
+
if (!cards || !open || closeRef.current) return;
|
|
7156
|
+
const active = document.activeElement;
|
|
7157
|
+
close({ by: "layout", focusInside: Boolean(active && contentRef.current?.contains(active)) });
|
|
7158
|
+
}, [cards, open]);
|
|
7012
7159
|
return /* @__PURE__ */ jsx38(
|
|
7013
7160
|
ContextMenu,
|
|
7014
7161
|
{
|
|
7015
7162
|
open: open && !gone,
|
|
7016
|
-
onOpenChange:
|
|
7163
|
+
onOpenChange: (next) => {
|
|
7164
|
+
if (!next) close({ by: "dismiss", outside: false });
|
|
7165
|
+
},
|
|
7017
7166
|
position,
|
|
7018
7167
|
contentProps: {
|
|
7019
7168
|
align: "start",
|
|
@@ -7027,13 +7176,15 @@ function RowContextMenu({
|
|
|
7027
7176
|
}
|
|
7028
7177
|
},
|
|
7029
7178
|
onInteractOutside: () => {
|
|
7030
|
-
|
|
7179
|
+
pressedOutside.current = true;
|
|
7180
|
+
close({ by: "dismiss", outside: true });
|
|
7031
7181
|
},
|
|
7032
7182
|
onCloseAutoFocus: (event) => {
|
|
7033
7183
|
event.preventDefault();
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7184
|
+
let reason = closeRef.current ?? { by: "dismiss", outside: false };
|
|
7185
|
+
if (pressedOutside.current && reason.by === "dismiss") reason = { by: "dismiss", outside: true };
|
|
7186
|
+
if (pressedOutside.current && reason.by === "layout") reason = { by: "layout", focusInside: false };
|
|
7187
|
+
onClose(menuKey, reason);
|
|
7037
7188
|
}
|
|
7038
7189
|
},
|
|
7039
7190
|
children: shownGroups.current.map((group, index) => /* @__PURE__ */ jsxs34(React35.Fragment, { children: [
|
|
@@ -7045,7 +7196,7 @@ function RowContextMenu({
|
|
|
7045
7196
|
{
|
|
7046
7197
|
item,
|
|
7047
7198
|
onPick: (picked) => {
|
|
7048
|
-
|
|
7199
|
+
closeRef.current ??= { by: "item", item: picked };
|
|
7049
7200
|
}
|
|
7050
7201
|
},
|
|
7051
7202
|
item.id
|
|
@@ -7130,7 +7281,7 @@ function MobileSortMenu({
|
|
|
7130
7281
|
size: "sm",
|
|
7131
7282
|
className: "ml-auto min-w-0",
|
|
7132
7283
|
children: [
|
|
7133
|
-
active && sortBy ? /* @__PURE__ */ jsxs34(
|
|
7284
|
+
active && sortBy ? /* @__PURE__ */ jsxs34(Fragment19, { children: [
|
|
7134
7285
|
/* @__PURE__ */ jsx38("span", { className: "sr-only", children: "\uC815\uB82C " }),
|
|
7135
7286
|
/* @__PURE__ */ jsx38("span", { className: "truncate", children: active.header }),
|
|
7136
7287
|
/* @__PURE__ */ jsxs34("span", { className: "sr-only", children: [
|
|
@@ -7403,7 +7554,7 @@ function DataTableRowView({
|
|
|
7403
7554
|
if (!expand) {
|
|
7404
7555
|
return dataRow;
|
|
7405
7556
|
}
|
|
7406
|
-
return /* @__PURE__ */ jsxs34(
|
|
7557
|
+
return /* @__PURE__ */ jsxs34(Fragment19, { children: [
|
|
7407
7558
|
dataRow,
|
|
7408
7559
|
/* @__PURE__ */ jsx38(
|
|
7409
7560
|
"div",
|
|
@@ -7640,8 +7791,8 @@ function useVirtualWindow({
|
|
|
7640
7791
|
padBottom: 0
|
|
7641
7792
|
});
|
|
7642
7793
|
const desktopSize = React35.useRef(0);
|
|
7643
|
-
const
|
|
7644
|
-
|
|
7794
|
+
const cardHeights = React35.useRef(null);
|
|
7795
|
+
cardHeights.current ??= new CardHeights();
|
|
7645
7796
|
const update = React35.useRef(() => void 0);
|
|
7646
7797
|
const reported = React35.useRef("");
|
|
7647
7798
|
const latest = React35.useRef({
|
|
@@ -7667,9 +7818,9 @@ function useVirtualWindow({
|
|
|
7667
7818
|
extent = uniformExtent(size);
|
|
7668
7819
|
} else {
|
|
7669
7820
|
if (list) {
|
|
7670
|
-
|
|
7821
|
+
cardHeights.current.measure(list);
|
|
7671
7822
|
}
|
|
7672
|
-
const { offsets, estimate } =
|
|
7823
|
+
const { offsets, estimate } = cardHeights.current.offsets(rowIds);
|
|
7673
7824
|
extent = measuredExtent(offsets, estimate);
|
|
7674
7825
|
}
|
|
7675
7826
|
latest.current = { count, layout, extent };
|
|
@@ -8015,15 +8166,22 @@ function DataTableInner({
|
|
|
8015
8166
|
contextMenuKey.current += 1;
|
|
8016
8167
|
setContextMenu({ rowId, position: { x: event.clientX, y: event.clientY }, key: contextMenuKey.current });
|
|
8017
8168
|
};
|
|
8018
|
-
const closeRowContextMenu = (
|
|
8169
|
+
const closeRowContextMenu = (key, close) => {
|
|
8170
|
+
if (key !== contextMenuKey.current) {
|
|
8171
|
+
return;
|
|
8172
|
+
}
|
|
8019
8173
|
const rowId = contextMenu?.rowId;
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
const
|
|
8023
|
-
|
|
8174
|
+
const refocus = close.by === "item" || (close.by === "dismiss" ? !close.outside : close.focusInside);
|
|
8175
|
+
if (rowId !== void 0 && refocus) {
|
|
8176
|
+
const cards = readLayout(desktopRef.current) === "mobile";
|
|
8177
|
+
const list = cards ? mobileListRef.current : desktopListRef.current;
|
|
8178
|
+
const row = Array.from(
|
|
8179
|
+
list?.querySelectorAll(cards ? '[data-slot="data-table-mobile-card"]' : '[data-slot="data-table-row"]') ?? []
|
|
8180
|
+
).find((node) => node.getAttribute("data-row-id") === rowId);
|
|
8181
|
+
const trigger = row?.querySelector(
|
|
8182
|
+
cards ? '[data-slot="list-card-actions"] button' : '[data-slot="data-table-row-actions"] button'
|
|
8024
8183
|
);
|
|
8025
|
-
const
|
|
8026
|
-
const target = trigger ?? (row?.hasAttribute("tabindex") ? row : null) ?? list ?? desktopRef.current;
|
|
8184
|
+
const target = trigger ?? (row && (cards || row.hasAttribute("tabindex")) ? row : null) ?? list ?? (cards ? mobileRef : desktopRef).current;
|
|
8027
8185
|
if (target) {
|
|
8028
8186
|
if (!target.hasAttribute("tabindex") && !target.matches("a[href],button,input")) {
|
|
8029
8187
|
target.tabIndex = -1;
|
|
@@ -8032,7 +8190,7 @@ function DataTableInner({
|
|
|
8032
8190
|
}
|
|
8033
8191
|
}
|
|
8034
8192
|
setContextMenu(null);
|
|
8035
|
-
item
|
|
8193
|
+
if (close.by === "item") close.item.onSelect();
|
|
8036
8194
|
};
|
|
8037
8195
|
const handleRowContextMenu = rowActions ? openRowContextMenu : onRowContextMenu;
|
|
8038
8196
|
const latestHandlers = React35.useRef({ toggleRow, activateRow, onRowContextMenu, handleRowContextMenu });
|
|
@@ -8284,14 +8442,16 @@ function DataTableInner({
|
|
|
8284
8442
|
)
|
|
8285
8443
|
] }),
|
|
8286
8444
|
footer != null ? /* @__PURE__ */ jsx38("div", { "data-slot": "data-table-footer", className: "border-t border-[var(--border-subtle)] empty:hidden", children: footer }) : null,
|
|
8287
|
-
hasRowActions ? /* @__PURE__ */ jsx38(
|
|
8445
|
+
hasRowActions && contextMenu ? /* @__PURE__ */ jsx38(
|
|
8288
8446
|
RowContextMenu,
|
|
8289
8447
|
{
|
|
8290
|
-
|
|
8291
|
-
position: contextMenu
|
|
8448
|
+
menuKey: contextMenu.key,
|
|
8449
|
+
position: contextMenu.position,
|
|
8292
8450
|
groups: contextGroups,
|
|
8451
|
+
cards: activeLayout === "mobile",
|
|
8293
8452
|
onClose: closeRowContextMenu
|
|
8294
|
-
}
|
|
8453
|
+
},
|
|
8454
|
+
contextMenu.key
|
|
8295
8455
|
) : null
|
|
8296
8456
|
]
|
|
8297
8457
|
}
|
|
@@ -8488,17 +8648,25 @@ function warnTrailingOnce() {
|
|
|
8488
8648
|
console.warn("BulkActionBar: the floating card ignores `trailing`. Put edit-mode controls at the right end of the toolbar.");
|
|
8489
8649
|
}
|
|
8490
8650
|
var OFFSET_PROPERTY = "--olun-bulk-bar-offset";
|
|
8491
|
-
var
|
|
8651
|
+
var LIFT_ZONE = 204;
|
|
8652
|
+
var cardOffsets = /* @__PURE__ */ new Map();
|
|
8492
8653
|
function writeOffset() {
|
|
8493
8654
|
const root = document.documentElement;
|
|
8494
|
-
const
|
|
8495
|
-
|
|
8655
|
+
const offset = Math.max(0, ...cardOffsets.values());
|
|
8656
|
+
const value = offset > 0 ? `${offset}px` : "";
|
|
8657
|
+
if (root.style.getPropertyValue(OFFSET_PROPERTY) === value) return;
|
|
8658
|
+
if (value) root.style.setProperty(OFFSET_PROPERTY, value);
|
|
8496
8659
|
else root.style.removeProperty(OFFSET_PROPERTY);
|
|
8497
8660
|
}
|
|
8498
|
-
function
|
|
8499
|
-
|
|
8500
|
-
if (
|
|
8501
|
-
|
|
8661
|
+
function reportOffset(key, card) {
|
|
8662
|
+
let offset = 0;
|
|
8663
|
+
if (card.offsetHeight > 0) {
|
|
8664
|
+
const { top, bottom } = card.getBoundingClientRect();
|
|
8665
|
+
if (window.innerHeight - bottom <= LIFT_ZONE) offset = Math.max(0, Math.round(window.innerHeight - top));
|
|
8666
|
+
}
|
|
8667
|
+
if (offset === (cardOffsets.get(key) ?? 0)) return;
|
|
8668
|
+
if (offset > 0) cardOffsets.set(key, offset);
|
|
8669
|
+
else cardOffsets.delete(key);
|
|
8502
8670
|
writeOffset();
|
|
8503
8671
|
}
|
|
8504
8672
|
var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React36.useEffect : React36.useLayoutEffect;
|
|
@@ -8506,20 +8674,80 @@ function useBottomOffset(card) {
|
|
|
8506
8674
|
const [key] = React36.useState(() => ({}));
|
|
8507
8675
|
React36.useEffect(() => {
|
|
8508
8676
|
if (!card) return;
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8677
|
+
let frame = 0;
|
|
8678
|
+
let stopped = false;
|
|
8679
|
+
let listening = false;
|
|
8680
|
+
const schedule = () => {
|
|
8681
|
+
if (frame || stopped) return;
|
|
8682
|
+
frame = requestAnimationFrame(measure);
|
|
8683
|
+
};
|
|
8684
|
+
const listen = (on) => {
|
|
8685
|
+
if (on === listening) return;
|
|
8686
|
+
listening = on;
|
|
8687
|
+
if (on) {
|
|
8688
|
+
window.addEventListener("resize", schedule);
|
|
8689
|
+
window.addEventListener("scroll", schedule, { capture: true, passive: true });
|
|
8690
|
+
} else {
|
|
8691
|
+
window.removeEventListener("resize", schedule);
|
|
8692
|
+
window.removeEventListener("scroll", schedule, { capture: true });
|
|
8693
|
+
}
|
|
8694
|
+
};
|
|
8695
|
+
let watcher = null;
|
|
8696
|
+
let watched = "";
|
|
8697
|
+
const arm = (margin, threshold) => {
|
|
8698
|
+
let first = true;
|
|
8699
|
+
watcher = new IntersectionObserver(
|
|
8700
|
+
([entry]) => {
|
|
8701
|
+
if (stopped) return;
|
|
8702
|
+
if (first) {
|
|
8703
|
+
first = false;
|
|
8704
|
+
if (entry.intersectionRatio === threshold) return;
|
|
8705
|
+
watcher?.disconnect();
|
|
8706
|
+
arm(margin, entry.intersectionRatio);
|
|
8707
|
+
}
|
|
8708
|
+
schedule();
|
|
8709
|
+
},
|
|
8710
|
+
{ root: document, rootMargin: margin, threshold }
|
|
8711
|
+
);
|
|
8712
|
+
watcher.observe(card);
|
|
8713
|
+
};
|
|
8714
|
+
const watch = (on) => {
|
|
8715
|
+
let margin = "";
|
|
8716
|
+
if (on && typeof IntersectionObserver !== "undefined") {
|
|
8717
|
+
const { top, right, bottom, left } = card.getBoundingClientRect();
|
|
8718
|
+
const { clientWidth, clientHeight } = document.documentElement;
|
|
8719
|
+
margin = [top, clientWidth - right, clientHeight - bottom, left].map((inset) => `${-Math.floor(inset)}px`).join(" ");
|
|
8720
|
+
}
|
|
8721
|
+
if (margin === watched) return;
|
|
8722
|
+
watched = margin;
|
|
8723
|
+
watcher?.disconnect();
|
|
8724
|
+
watcher = null;
|
|
8725
|
+
if (margin) arm(margin, 1);
|
|
8726
|
+
};
|
|
8727
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => schedule());
|
|
8728
|
+
const measure = () => {
|
|
8729
|
+
frame = 0;
|
|
8730
|
+
reportOffset(key, card);
|
|
8731
|
+
const shown = card.offsetHeight > 0;
|
|
8732
|
+
listen(shown || !observer);
|
|
8733
|
+
watch(shown);
|
|
8734
|
+
};
|
|
8735
|
+
measure();
|
|
8512
8736
|
observer?.observe(card);
|
|
8513
|
-
|
|
8737
|
+
card.addEventListener("animationend", schedule);
|
|
8514
8738
|
return () => {
|
|
8739
|
+
stopped = true;
|
|
8740
|
+
cancelAnimationFrame(frame);
|
|
8741
|
+
listen(false);
|
|
8742
|
+
watcher?.disconnect();
|
|
8515
8743
|
observer?.disconnect();
|
|
8516
|
-
|
|
8517
|
-
|
|
8744
|
+
card.removeEventListener("animationend", schedule);
|
|
8745
|
+
cardOffsets.delete(key);
|
|
8518
8746
|
writeOffset();
|
|
8519
8747
|
};
|
|
8520
8748
|
}, [key, card]);
|
|
8521
8749
|
useIsomorphicLayoutEffect2(() => {
|
|
8522
|
-
if (card && typeof ResizeObserver === "undefined")
|
|
8750
|
+
if (card && typeof ResizeObserver === "undefined") reportOffset(key, card);
|
|
8523
8751
|
});
|
|
8524
8752
|
}
|
|
8525
8753
|
function useCompactSummary(slot, enabled) {
|
|
@@ -10155,7 +10383,7 @@ function TablePagination({
|
|
|
10155
10383
|
|
|
10156
10384
|
// src/components/ui/mode-toggle.tsx
|
|
10157
10385
|
import { cva as cva19 } from "class-variance-authority";
|
|
10158
|
-
import { jsx as jsx56, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
10386
|
+
import { Fragment as Fragment20, jsx as jsx56, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
10159
10387
|
var modeToggleVariants = cva19(
|
|
10160
10388
|
[
|
|
10161
10389
|
"inline-flex items-center rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
|
|
@@ -10178,6 +10406,17 @@ var modeToggleItemVariants = cva19(
|
|
|
10178
10406
|
"[&_svg]:pointer-events-none [&_svg]:size-[14px] [&_svg]:shrink-0 [&_svg]:stroke-[1.75]"
|
|
10179
10407
|
].join(" ")
|
|
10180
10408
|
);
|
|
10409
|
+
function formatModeToggleCount(value) {
|
|
10410
|
+
return value > 99 ? "99+" : String(value);
|
|
10411
|
+
}
|
|
10412
|
+
function isShownModeToggleCount(value) {
|
|
10413
|
+
if (value === void 0) return false;
|
|
10414
|
+
if (Number.isInteger(value) && value >= 0) return true;
|
|
10415
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
10416
|
+
console.warn(`ModeToggle: count must be an integer 0 or greater (got ${value}). The count is not shown.`);
|
|
10417
|
+
}
|
|
10418
|
+
return false;
|
|
10419
|
+
}
|
|
10181
10420
|
function ModeToggle({
|
|
10182
10421
|
className,
|
|
10183
10422
|
itemClassName,
|
|
@@ -10218,7 +10457,11 @@ function ModeToggle({
|
|
|
10218
10457
|
},
|
|
10219
10458
|
children: [
|
|
10220
10459
|
Icon ? /* @__PURE__ */ jsx56(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
|
|
10221
|
-
/* @__PURE__ */ jsx56("span", { children: option.label })
|
|
10460
|
+
/* @__PURE__ */ jsx56("span", { children: option.label }),
|
|
10461
|
+
isShownModeToggleCount(option.count) ? /* @__PURE__ */ jsxs45(Fragment20, { children: [
|
|
10462
|
+
/* @__PURE__ */ jsx56("span", { "aria-hidden": "true", "data-slot": "mode-toggle-count", className: tabsBadgeVariants(), children: formatModeToggleCount(option.count) }),
|
|
10463
|
+
/* @__PURE__ */ jsx56("span", { className: "sr-only", children: ` ${option.count}` })
|
|
10464
|
+
] }) : null
|
|
10222
10465
|
]
|
|
10223
10466
|
},
|
|
10224
10467
|
option.value
|
|
@@ -10667,7 +10910,7 @@ function ToastProvider({ children, maxToasts = 3, className, ...props }) {
|
|
|
10667
10910
|
import * as React48 from "react";
|
|
10668
10911
|
import { cva as cva22 } from "class-variance-authority";
|
|
10669
10912
|
import { AlertCircle as AlertCircle4 } from "lucide-react";
|
|
10670
|
-
import { Fragment as
|
|
10913
|
+
import { Fragment as Fragment21, jsx as jsx59, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
10671
10914
|
var otpFieldVariants = cva22("flex w-full min-w-0 flex-col gap-[var(--space-3)]", {
|
|
10672
10915
|
variants: {
|
|
10673
10916
|
size: {
|
|
@@ -10997,7 +11240,7 @@ var OTPField = React48.forwardRef(
|
|
|
10997
11240
|
"data-slot": "otp-field-message",
|
|
10998
11241
|
"data-kind": errorText ? "error" : "helper",
|
|
10999
11242
|
className: otpFieldMessageVariants({ state: resolvedState }),
|
|
11000
|
-
children: errorText ? /* @__PURE__ */ jsxs48(
|
|
11243
|
+
children: errorText ? /* @__PURE__ */ jsxs48(Fragment21, { children: [
|
|
11001
11244
|
/* @__PURE__ */ jsx59(
|
|
11002
11245
|
AlertCircle4,
|
|
11003
11246
|
{
|
|
@@ -11885,7 +12128,7 @@ function TreeView({
|
|
|
11885
12128
|
|
|
11886
12129
|
// src/components/branding/olun-logo.tsx
|
|
11887
12130
|
import { OLUN_MASTER, OLUN_SYMBOL, OLUN_WORDMARK } from "@olundot/tokens/brand";
|
|
11888
|
-
import { Fragment as
|
|
12131
|
+
import { Fragment as Fragment22, jsx as jsx66, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
11889
12132
|
var ACCENT_FILL = "var(--accent-pop)";
|
|
11890
12133
|
var INK = { color: "var(--text-primary)" };
|
|
11891
12134
|
var INK_TIGHT = { ...INK, display: "block", overflow: "visible" };
|
|
@@ -11895,7 +12138,7 @@ function symbolGeometry(size) {
|
|
|
11895
12138
|
function SymbolCircles({ size }) {
|
|
11896
12139
|
const { ring } = OLUN_SYMBOL;
|
|
11897
12140
|
const g = symbolGeometry(size);
|
|
11898
|
-
return /* @__PURE__ */ jsxs53(
|
|
12141
|
+
return /* @__PURE__ */ jsxs53(Fragment22, { children: [
|
|
11899
12142
|
/* @__PURE__ */ jsx66(
|
|
11900
12143
|
"circle",
|
|
11901
12144
|
{
|