@olundot/ui 0.20.1 → 0.20.2
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 +15 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +76 -34
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @olundot/ui
|
|
2
2
|
|
|
3
|
+
## 0.20.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8a28822: `FilterToolbar layout="grid"`은 640px 미만에서 `filters`도 시트로 보낸다. 줄에는 검색, 접힌 필터 버튼, `actions`만 남고, 시트에는 `filters`를 순서대로 둔 뒤 `collapsible`을 둔다.
|
|
8
|
+
|
|
9
|
+
- 폭을 재기 전 첫 화면에서도 640px 미만이면 줄 필터를 펼치지 않는다. 컨테이너 쿼리로 숨기고, 폭을 잰 뒤에는 줄에 그리지 않는다.
|
|
10
|
+
- `collapsible` 없이 `filters`만 있어도 640px 미만에서 버튼과 시트가 생긴다.
|
|
11
|
+
- `activeLineFilterCount`: `filters` 중 적용한 조건 수. 640px 미만에서 버튼 배지, 버튼 이름, 적용 개수 줄의 개수에 더한다.
|
|
12
|
+
- `onClearLineFilters`: 640px 미만의 "해제"가 `onClearFilters`와 함께 부른다.
|
|
13
|
+
- 격자의 `filters`와 `collapsible` 컨트롤은 줄과 시트를 오가며 새로 그려지므로 값은 `value`로 넘긴다. `defaultValue`로 둔 값은 시트를 닫으면 남지 않는다.
|
|
14
|
+
- 두 prop을 주지 않으면 640px 미만 개수와 "해제"는 `collapsible` 조건만 다룬다. 640px 이상 격자와 `layout="flow"`는 그대로다.
|
|
15
|
+
- 격자에서 `collapseBelow="never"`도 `collapsible`을 줄에 펼치지 않는다.
|
|
16
|
+
- 격자는 툴바 폭을 컨테이너 쿼리와 같은 기준(내용 상자, CSS `zoom` 전)으로 잰다.
|
|
17
|
+
|
|
3
18
|
## 0.20.1
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -903,6 +903,10 @@ interface FilterToolbarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
903
903
|
collapseBelow?: FilterToolbarCollapseBelow;
|
|
904
904
|
activeFilterCount?: number;
|
|
905
905
|
onClearFilters?: () => void;
|
|
906
|
+
/** grid: applied conditions among `filters`. Under 640px the count adds them. */
|
|
907
|
+
activeLineFilterCount?: number;
|
|
908
|
+
/** grid: under 640px 해제 calls it with `onClearFilters`. */
|
|
909
|
+
onClearLineFilters?: () => void;
|
|
906
910
|
collapsedLabel?: string;
|
|
907
911
|
resultSummary?: React.ReactNode;
|
|
908
912
|
clearAction?: React.ReactNode;
|
package/dist/index.js
CHANGED
|
@@ -5737,14 +5737,8 @@ var collapsibleClassNames = {
|
|
|
5737
5737
|
trigger: "hidden"
|
|
5738
5738
|
}
|
|
5739
5739
|
};
|
|
5740
|
-
var gridCollapsibleClassNames = {
|
|
5741
|
-
sm: { inline: "hidden", trigger: "" },
|
|
5742
|
-
md: { inline: "hidden", trigger: "" },
|
|
5743
|
-
lg: { inline: "hidden", trigger: "" },
|
|
5744
|
-
never: { inline: "flex @[640px]:hidden", trigger: "hidden @[640px]:inline" }
|
|
5745
|
-
};
|
|
5746
5740
|
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%]";
|
|
5747
|
-
var gridFiltersClassName = "order-3
|
|
5741
|
+
var gridFiltersClassName = "order-3 hidden min-w-0 flex-[1_0_100%] flex-wrap items-center gap-[var(--space-2)] @[640px]:contents";
|
|
5748
5742
|
var gridCellClassName = cn(
|
|
5749
5743
|
"contents @[640px]:block @[640px]:order-3 @[640px]:min-w-0 @[640px]:flex-[3_1_0%]",
|
|
5750
5744
|
"@[640px]:[&:has([data-slot=select-trigger])]:flex-[2_1_0%]",
|
|
@@ -5766,6 +5760,10 @@ function filterCells(node, prefix = "") {
|
|
|
5766
5760
|
return React31.isValidElement(child) && child.type === React31.Fragment ? filterCells(child.props.children, `${key}/`) : [{ key, cell: child }];
|
|
5767
5761
|
});
|
|
5768
5762
|
}
|
|
5763
|
+
function contentWidth(element) {
|
|
5764
|
+
const style = getComputedStyle(element);
|
|
5765
|
+
return element.clientWidth - (parseFloat(style.paddingLeft) || 0) - (parseFloat(style.paddingRight) || 0);
|
|
5766
|
+
}
|
|
5769
5767
|
function warnGridFilters(count) {
|
|
5770
5768
|
if (typeof process === "undefined" || process.env.NODE_ENV === "production") return;
|
|
5771
5769
|
console.warn(
|
|
@@ -5781,6 +5779,8 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5781
5779
|
collapseBelow = "lg",
|
|
5782
5780
|
activeFilterCount: activeFilterCountProp,
|
|
5783
5781
|
onClearFilters,
|
|
5782
|
+
activeLineFilterCount,
|
|
5783
|
+
onClearLineFilters,
|
|
5784
5784
|
collapsedLabel = "\uD544\uD130",
|
|
5785
5785
|
resultSummary,
|
|
5786
5786
|
clearAction,
|
|
@@ -5796,6 +5796,7 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5796
5796
|
null
|
|
5797
5797
|
);
|
|
5798
5798
|
const [overlayOpen, setOverlayOpen] = React31.useState(false);
|
|
5799
|
+
const rootRef = React31.useRef(null);
|
|
5799
5800
|
const triggerRef = React31.useRef(null);
|
|
5800
5801
|
const rowRef = React31.useRef(null);
|
|
5801
5802
|
const chipsRef = React31.useRef(null);
|
|
@@ -5803,28 +5804,31 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5803
5804
|
const pendingFocusRef = React31.useRef(null);
|
|
5804
5805
|
const setRootRefs = React31.useCallback(
|
|
5805
5806
|
(element) => {
|
|
5807
|
+
rootRef.current = element;
|
|
5806
5808
|
setRootElement(element);
|
|
5807
5809
|
if (typeof ref === "function") ref(element);
|
|
5808
5810
|
else if (ref) ref.current = element;
|
|
5809
5811
|
},
|
|
5810
5812
|
[ref]
|
|
5811
5813
|
);
|
|
5814
|
+
const isGrid = layout === "grid";
|
|
5812
5815
|
React31.useEffect(() => {
|
|
5813
5816
|
if (!rootElement) return;
|
|
5814
|
-
const updateWidth = () => {
|
|
5815
|
-
setContainerWidth(
|
|
5817
|
+
const updateWidth = (entry) => {
|
|
5818
|
+
setContainerWidth(
|
|
5819
|
+
isGrid ? entry?.contentBoxSize?.[0]?.inlineSize ?? contentWidth(rootElement) : rootElement.getBoundingClientRect().width
|
|
5820
|
+
);
|
|
5816
5821
|
};
|
|
5817
5822
|
updateWidth();
|
|
5818
5823
|
if (typeof ResizeObserver === "undefined") return;
|
|
5819
|
-
const observer = new ResizeObserver(updateWidth);
|
|
5824
|
+
const observer = new ResizeObserver(([entry]) => updateWidth(entry));
|
|
5820
5825
|
observer.observe(rootElement);
|
|
5821
5826
|
return () => observer.disconnect();
|
|
5822
|
-
}, [rootElement]);
|
|
5827
|
+
}, [rootElement, isGrid]);
|
|
5823
5828
|
const handleOverlayOpenChange = React31.useCallback((open) => {
|
|
5824
5829
|
setOverlayOpen(open);
|
|
5825
5830
|
if (!open) queueMicrotask(() => triggerRef.current?.focus());
|
|
5826
5831
|
}, []);
|
|
5827
|
-
const isGrid = layout === "grid";
|
|
5828
5832
|
const gridCells = isGrid ? filterCells(filters) : [];
|
|
5829
5833
|
const filterCellCount = gridCells.length;
|
|
5830
5834
|
React31.useEffect(() => {
|
|
@@ -5866,33 +5870,67 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5866
5870
|
const hasAppliedFilters = activeFilterCount > 0;
|
|
5867
5871
|
const hasAppliedChips = Boolean(appliedFilters && appliedFilters.length > 0);
|
|
5868
5872
|
const usesSheet = containerWidth !== null && containerWidth < 640;
|
|
5869
|
-
const
|
|
5870
|
-
const
|
|
5871
|
-
const
|
|
5873
|
+
const gridSheet = isGrid && Boolean(filters);
|
|
5874
|
+
const linesInSheet = gridSheet && usesSheet;
|
|
5875
|
+
const lineFilterCount = gridSheet ? activeLineFilterCount ?? 0 : 0;
|
|
5876
|
+
const narrowFilterCount = activeFilterCount + lineFilterCount;
|
|
5877
|
+
const hasCollapsed = Boolean(collapsible) || gridSheet;
|
|
5878
|
+
const outgrownSheet = isGrid && !collapsible && containerWidth !== null && containerWidth >= 640 && overlayOpen;
|
|
5879
|
+
React31.useEffect(() => {
|
|
5880
|
+
if (!outgrownSheet) return;
|
|
5881
|
+
setOverlayOpen(false);
|
|
5882
|
+
const ownerDocument = rootElement?.ownerDocument;
|
|
5883
|
+
const active = ownerDocument?.activeElement;
|
|
5884
|
+
if (!ownerDocument || active && active !== ownerDocument.body && active.isConnected) return;
|
|
5885
|
+
const cell = rowRef.current?.querySelector('[data-slot="filter-toolbar-cell"]');
|
|
5886
|
+
[...cell?.querySelectorAll(focusableSelector) ?? []].find(canTakeFocus)?.focus();
|
|
5887
|
+
}, [outgrownSheet, rootElement]);
|
|
5888
|
+
const inlineClassName = isGrid ? "hidden" : collapsibleClassNames[collapseBelow].inline;
|
|
5889
|
+
const triggerClassName = isGrid ? collapsible ? "" : "@[640px]:hidden" : collapsibleClassNames[collapseBelow].trigger;
|
|
5890
|
+
const triggerCount = linesInSheet ? narrowFilterCount : activeFilterCount;
|
|
5891
|
+
const collapseTriggerLabel = triggerCount > 0 ? `${collapsedLabel}, ${triggerCount}\uAC1C \uC801\uC6A9` : collapsedLabel;
|
|
5892
|
+
const narrowOnlyCount = !hasAppliedFilters && narrowFilterCount > 0;
|
|
5893
|
+
const countText = narrowFilterCount === activeFilterCount || narrowOnlyCount ? narrowFilterCount : /* @__PURE__ */ jsxs28(Fragment14, { children: [
|
|
5894
|
+
/* @__PURE__ */ jsx32("span", { className: "@[640px]:hidden", children: narrowFilterCount }),
|
|
5895
|
+
/* @__PURE__ */ jsx32("span", { className: "hidden @[640px]:inline", children: activeFilterCount })
|
|
5896
|
+
] });
|
|
5897
|
+
const clearLineFilters = gridSheet ? onClearLineFilters : void 0;
|
|
5898
|
+
const clearNarrow = onClearFilters && clearLineFilters ? () => {
|
|
5899
|
+
onClearFilters();
|
|
5900
|
+
clearLineFilters();
|
|
5901
|
+
} : onClearFilters ?? clearLineFilters;
|
|
5902
|
+
const clearFilters = () => {
|
|
5903
|
+
const width = containerWidth ?? (rootRef.current ? contentWidth(rootRef.current) : null);
|
|
5904
|
+
(width !== null && width < 640 ? clearNarrow : onClearFilters)?.();
|
|
5905
|
+
};
|
|
5906
|
+
const clearFiltersButton = (linesInSheet ? clearNarrow : onClearFilters) ? /* @__PURE__ */ jsx32(
|
|
5872
5907
|
"button",
|
|
5873
5908
|
{
|
|
5874
5909
|
type: "button",
|
|
5875
5910
|
"data-slot": "filter-toolbar-clear-filters",
|
|
5876
5911
|
className: "cursor-pointer border-0 bg-transparent p-0 text-body-sm font-medium text-text-secondary no-underline",
|
|
5877
|
-
onClick:
|
|
5912
|
+
onClick: clearFilters,
|
|
5878
5913
|
children: "\uD574\uC81C"
|
|
5879
5914
|
}
|
|
5880
5915
|
) : null;
|
|
5881
|
-
const collapsedContent =
|
|
5916
|
+
const collapsedContent = hasCollapsed ? /* @__PURE__ */ jsxs28(
|
|
5882
5917
|
"div",
|
|
5883
5918
|
{
|
|
5884
5919
|
"data-slot": "filter-toolbar-collapsed-content",
|
|
5885
5920
|
className: "flex flex-col gap-[var(--space-3)] [&>*]:w-full",
|
|
5886
|
-
children:
|
|
5921
|
+
children: [
|
|
5922
|
+
linesInSheet ? filters : null,
|
|
5923
|
+
collapsible
|
|
5924
|
+
]
|
|
5887
5925
|
}
|
|
5888
5926
|
) : null;
|
|
5889
|
-
const collapseTrigger =
|
|
5927
|
+
const collapseTrigger = hasCollapsed ? /* @__PURE__ */ jsxs28(
|
|
5890
5928
|
"span",
|
|
5891
5929
|
{
|
|
5892
5930
|
"data-slot": "filter-toolbar-collapse-trigger",
|
|
5893
5931
|
className: cn(
|
|
5894
5932
|
"relative order-2 shrink-0 @[640px]:order-4",
|
|
5895
|
-
|
|
5933
|
+
triggerClassName
|
|
5896
5934
|
),
|
|
5897
5935
|
children: [
|
|
5898
5936
|
/* @__PURE__ */ jsx32(
|
|
@@ -5907,16 +5945,17 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5907
5945
|
onClick: () => handleOverlayOpenChange(true)
|
|
5908
5946
|
}
|
|
5909
5947
|
),
|
|
5910
|
-
|
|
5948
|
+
narrowFilterCount > 0 ? /* @__PURE__ */ jsx32(
|
|
5911
5949
|
"span",
|
|
5912
5950
|
{
|
|
5913
5951
|
"aria-hidden": "true",
|
|
5914
5952
|
"data-slot": "filter-toolbar-collapse-count",
|
|
5915
5953
|
className: cn(
|
|
5916
5954
|
chipCountVariants({ tone: "accent", size: "md" }),
|
|
5917
|
-
"pointer-events-none absolute right-0 top-0 translate-x-1/3 -translate-y-1/3"
|
|
5955
|
+
"pointer-events-none absolute right-0 top-0 translate-x-1/3 -translate-y-1/3",
|
|
5956
|
+
narrowOnlyCount && "@[640px]:hidden"
|
|
5918
5957
|
),
|
|
5919
|
-
children:
|
|
5958
|
+
children: countText
|
|
5920
5959
|
}
|
|
5921
5960
|
) : null
|
|
5922
5961
|
]
|
|
@@ -5952,7 +5991,7 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5952
5991
|
children: search
|
|
5953
5992
|
}
|
|
5954
5993
|
) : null,
|
|
5955
|
-
|
|
5994
|
+
hasCollapsed && (usesSheet || !collapsible) ? collapseTrigger : null,
|
|
5956
5995
|
collapsible && !usesSheet ? /* @__PURE__ */ jsxs28(Popover, { open: overlayOpen, onOpenChange: handleOverlayOpenChange, children: [
|
|
5957
5996
|
/* @__PURE__ */ jsx32(PopoverAnchor, { asChild: true, children: collapseTrigger }),
|
|
5958
5997
|
overlayOpen ? /* @__PURE__ */ jsxs28(
|
|
@@ -5971,7 +6010,7 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5971
6010
|
}
|
|
5972
6011
|
) : null
|
|
5973
6012
|
] }) : null,
|
|
5974
|
-
filters ? /* @__PURE__ */ jsx32(
|
|
6013
|
+
filters && !linesInSheet ? /* @__PURE__ */ jsx32(
|
|
5975
6014
|
"div",
|
|
5976
6015
|
{
|
|
5977
6016
|
"data-slot": "filter-toolbar-filters",
|
|
@@ -5993,7 +6032,7 @@ var FilterToolbar = React31.forwardRef(
|
|
|
5993
6032
|
"data-slot": "filter-toolbar-collapsible",
|
|
5994
6033
|
className: cn(
|
|
5995
6034
|
"order-5 min-w-0 items-center gap-[var(--space-2)]",
|
|
5996
|
-
|
|
6035
|
+
inlineClassName
|
|
5997
6036
|
),
|
|
5998
6037
|
children: collapsible
|
|
5999
6038
|
}
|
|
@@ -6009,7 +6048,7 @@ var FilterToolbar = React31.forwardRef(
|
|
|
6009
6048
|
]
|
|
6010
6049
|
}
|
|
6011
6050
|
) : null,
|
|
6012
|
-
|
|
6051
|
+
hasCollapsed && usesSheet && overlayOpen ? /* @__PURE__ */ jsx32(
|
|
6013
6052
|
Sheet,
|
|
6014
6053
|
{
|
|
6015
6054
|
open: overlayOpen,
|
|
@@ -6070,28 +6109,31 @@ var FilterToolbar = React31.forwardRef(
|
|
|
6070
6109
|
]
|
|
6071
6110
|
}
|
|
6072
6111
|
) : null,
|
|
6073
|
-
|
|
6112
|
+
narrowFilterCount > 0 ? /* @__PURE__ */ jsxs28(
|
|
6074
6113
|
"div",
|
|
6075
6114
|
{
|
|
6076
6115
|
"data-slot": "filter-toolbar-applied",
|
|
6077
6116
|
className: cn(
|
|
6078
6117
|
"flex items-center gap-[var(--space-1)] text-[11px] text-text-tertiary",
|
|
6079
|
-
hasAppliedChips && "@[640px]:hidden"
|
|
6118
|
+
(hasAppliedChips || narrowOnlyCount) && "@[640px]:hidden"
|
|
6080
6119
|
),
|
|
6081
6120
|
children: [
|
|
6082
6121
|
/* @__PURE__ */ jsxs28("span", { children: [
|
|
6083
6122
|
"\uD544\uD130 ",
|
|
6084
|
-
|
|
6123
|
+
countText,
|
|
6085
6124
|
"\uAC1C \uC801\uC6A9"
|
|
6086
6125
|
] }),
|
|
6087
|
-
|
|
6088
|
-
/* @__PURE__ */ jsx32("span", { "aria-hidden": "true", children: " \xB7 " }),
|
|
6126
|
+
clearNarrow ? /* @__PURE__ */ jsxs28(Fragment14, { children: [
|
|
6127
|
+
/* @__PURE__ */ jsx32("span", { "aria-hidden": "true", className: onClearFilters ? void 0 : "@[640px]:hidden", children: " \xB7 " }),
|
|
6089
6128
|
/* @__PURE__ */ jsx32(
|
|
6090
6129
|
"button",
|
|
6091
6130
|
{
|
|
6092
6131
|
type: "button",
|
|
6093
|
-
className:
|
|
6094
|
-
|
|
6132
|
+
className: cn(
|
|
6133
|
+
"cursor-pointer border-0 bg-transparent p-0 text-[11px] text-text-secondary no-underline",
|
|
6134
|
+
!onClearFilters && "@[640px]:hidden"
|
|
6135
|
+
),
|
|
6136
|
+
onClick: clearFilters,
|
|
6095
6137
|
children: "\uD574\uC81C"
|
|
6096
6138
|
}
|
|
6097
6139
|
)
|