@exem-ui/react 0.3.4-next.20260622062509 → 0.3.4-next.20260623023915

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -635,6 +635,21 @@ type ModalComponent = typeof DialogPrimitive.Root & {
635
635
  };
636
636
  declare const Modal: ModalComponent;
637
637
 
638
+ type SheetResizeOptions = {
639
+ /** @default true (객체를 전달한 경우) */
640
+ use?: boolean;
641
+ /** 최소 크기(px). 기본: left/right 400, top/bottom 300 */
642
+ minSize?: number;
643
+ /** 최대 크기(px 또는 '80%'). 퍼센트는 뷰포트 기준. @default '80%' */
644
+ maxSize?: number | string;
645
+ /** 기본 크기(px). 기본: left/right 800, top/bottom 600 */
646
+ defaultSize?: number;
647
+ /** 지정 시 localStorage에 크기를 저장/복원 */
648
+ storageKey?: string;
649
+ /** 드래그 종료 시 최종 크기(px) 콜백 */
650
+ onResize?: (size: number) => void;
651
+ };
652
+
638
653
  type SheetSide = 'top' | 'right' | 'bottom' | 'left';
639
654
  type SheetRootProps = React__default.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>;
640
655
  type SheetTriggerProps = React__default.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>;
@@ -646,6 +661,11 @@ type SheetContentProps = React__default.ComponentPropsWithoutRef<typeof DialogPr
646
661
  * @default 'right'
647
662
  */
648
663
  side?: SheetSide;
664
+ /**
665
+ * 드래그 리사이징. `true` 또는 옵션 객체로 활성화.
666
+ * @default false
667
+ */
668
+ resizable?: boolean | SheetResizeOptions;
649
669
  };
650
670
  type SheetCloseProps = React__default.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>;
651
671
  type SheetHeaderProps = React__default.HTMLAttributes<HTMLDivElement> & {
package/dist/index.d.ts CHANGED
@@ -635,6 +635,21 @@ type ModalComponent = typeof DialogPrimitive.Root & {
635
635
  };
636
636
  declare const Modal: ModalComponent;
637
637
 
638
+ type SheetResizeOptions = {
639
+ /** @default true (객체를 전달한 경우) */
640
+ use?: boolean;
641
+ /** 최소 크기(px). 기본: left/right 400, top/bottom 300 */
642
+ minSize?: number;
643
+ /** 최대 크기(px 또는 '80%'). 퍼센트는 뷰포트 기준. @default '80%' */
644
+ maxSize?: number | string;
645
+ /** 기본 크기(px). 기본: left/right 800, top/bottom 600 */
646
+ defaultSize?: number;
647
+ /** 지정 시 localStorage에 크기를 저장/복원 */
648
+ storageKey?: string;
649
+ /** 드래그 종료 시 최종 크기(px) 콜백 */
650
+ onResize?: (size: number) => void;
651
+ };
652
+
638
653
  type SheetSide = 'top' | 'right' | 'bottom' | 'left';
639
654
  type SheetRootProps = React__default.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>;
640
655
  type SheetTriggerProps = React__default.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>;
@@ -646,6 +661,11 @@ type SheetContentProps = React__default.ComponentPropsWithoutRef<typeof DialogPr
646
661
  * @default 'right'
647
662
  */
648
663
  side?: SheetSide;
664
+ /**
665
+ * 드래그 리사이징. `true` 또는 옵션 객체로 활성화.
666
+ * @default false
667
+ */
668
+ resizable?: boolean | SheetResizeOptions;
649
669
  };
650
670
  type SheetCloseProps = React__default.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>;
651
671
  type SheetHeaderProps = React__default.HTMLAttributes<HTMLDivElement> & {
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ var reactDayPicker = require('react-day-picker');
13
13
  var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
14
14
  var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
15
15
  var DialogPrimitive = require('@radix-ui/react-dialog');
16
+ var reResizable = require('re-resizable');
16
17
  var sonner = require('sonner');
17
18
 
18
19
  function _interopNamespace(e) {
@@ -1886,13 +1887,131 @@ Modal.Actions.displayName = "Modal.Actions";
1886
1887
  Modal.Action.displayName = "Modal.Action";
1887
1888
  Modal.Title.displayName = "Modal.Title";
1888
1889
  Modal.Description.displayName = "Modal.Description";
1890
+
1891
+ // src/sheet/sheetResize.ts
1889
1892
  var SHEET_EDGE_GAP = "[--sheet-edge-gap:40px]";
1893
+ var getAxis = (side) => side === "left" || side === "right" ? "horizontal" : "vertical";
1894
+ var getDefaults = (axis) => axis === "horizontal" ? { minSize: 400, maxSize: "80%", defaultSize: 800 } : { minSize: 300, maxSize: "80%", defaultSize: 600 };
1895
+ var resolveMaxSize = (maxSize, axis) => {
1896
+ if (typeof maxSize === "number") {
1897
+ return maxSize;
1898
+ }
1899
+ const value = Number.parseFloat(maxSize);
1900
+ if (maxSize.trim().endsWith("%") && Number.isFinite(value)) {
1901
+ return `${value}${axis === "horizontal" ? "vw" : "vh"}`;
1902
+ }
1903
+ return maxSize;
1904
+ };
1905
+ var STORAGE_PREFIX = "exem-ui:sheet-size:";
1906
+ var readStoredSize = (key) => {
1907
+ if (typeof window === "undefined") {
1908
+ return null;
1909
+ }
1910
+ try {
1911
+ const raw = window.localStorage.getItem(STORAGE_PREFIX + key);
1912
+ if (raw == null) {
1913
+ return null;
1914
+ }
1915
+ const value = Number.parseFloat(raw);
1916
+ return Number.isFinite(value) ? value : null;
1917
+ } catch {
1918
+ return null;
1919
+ }
1920
+ };
1921
+ var writeStoredSize = (key, size) => {
1922
+ if (typeof window === "undefined") {
1923
+ return;
1924
+ }
1925
+ try {
1926
+ window.localStorage.setItem(STORAGE_PREFIX + key, String(size));
1927
+ } catch {
1928
+ }
1929
+ };
1930
+ var ENABLE_BY_SIDE = {
1931
+ right: { left: true },
1932
+ left: { right: true },
1933
+ top: { bottom: true },
1934
+ bottom: { top: true }
1935
+ };
1936
+ var HANDLE_EDGE_BY_SIDE = {
1937
+ right: "left",
1938
+ left: "right",
1939
+ top: "bottom",
1940
+ bottom: "top"
1941
+ };
1942
+ var SheetResizeHandle = ({ axis, active }) => /* @__PURE__ */ jsxRuntime.jsx(
1943
+ "div",
1944
+ {
1945
+ className: utils.cn(
1946
+ "group/sheet-handle flex h-full w-full items-center justify-center",
1947
+ axis === "horizontal" ? "cursor-col-resize" : "cursor-row-resize"
1948
+ ),
1949
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1950
+ "span",
1951
+ {
1952
+ className: utils.cn(
1953
+ "transition-colors group-hover/sheet-handle:bg-border-accent",
1954
+ active ? "bg-border-accent" : "bg-border-primary",
1955
+ axis === "horizontal" ? "h-full w-px" : "h-px w-full"
1956
+ )
1957
+ }
1958
+ )
1959
+ }
1960
+ );
1961
+ var SheetResizableBox = ({ side, options, children }) => {
1962
+ const { minSize, maxSize, defaultSize, storageKey, onResize } = options;
1963
+ const axis = getAxis(side);
1964
+ const isHorizontal = axis === "horizontal";
1965
+ const defaults = getDefaults(axis);
1966
+ const resolvedMin = minSize ?? defaults.minSize;
1967
+ const resolvedMax = resolveMaxSize(maxSize ?? defaults.maxSize, axis);
1968
+ const [initialSize] = React.useState(() => {
1969
+ const stored = storageKey ? readStoredSize(storageKey) : null;
1970
+ return Math.max(stored ?? defaultSize ?? defaults.defaultSize, resolvedMin);
1971
+ });
1972
+ const [resizing, setResizing] = React.useState(false);
1973
+ const handleResizeStop = (_event, _direction, refElement) => {
1974
+ setResizing(false);
1975
+ const next = isHorizontal ? refElement.offsetWidth : refElement.offsetHeight;
1976
+ if (storageKey) {
1977
+ writeStoredSize(storageKey, next);
1978
+ }
1979
+ onResize?.(next);
1980
+ };
1981
+ const handleComponent = {
1982
+ [HANDLE_EDGE_BY_SIDE[side]]: /* @__PURE__ */ jsxRuntime.jsx(SheetResizeHandle, { axis, active: resizing })
1983
+ };
1984
+ return /* @__PURE__ */ jsxRuntime.jsx(
1985
+ reResizable.Resizable,
1986
+ {
1987
+ enable: ENABLE_BY_SIDE[side],
1988
+ defaultSize: isHorizontal ? { width: initialSize, height: "100%" } : { width: "100%", height: initialSize },
1989
+ minWidth: isHorizontal ? resolvedMin : void 0,
1990
+ maxWidth: isHorizontal ? resolvedMax : void 0,
1991
+ minHeight: isHorizontal ? void 0 : resolvedMin,
1992
+ maxHeight: isHorizontal ? void 0 : resolvedMax,
1993
+ onResizeStart: () => setResizing(true),
1994
+ onResizeStop: handleResizeStop,
1995
+ handleComponent,
1996
+ className: "flex min-h-0 flex-col bg-elevation-elevation-0 shadow-strong",
1997
+ children
1998
+ }
1999
+ );
2000
+ };
2001
+ var SHEET_CONTENT_BASE = "fixed z-50 data-[state=open]:duration-300 data-[state=closed]:duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0";
2002
+ var SHEET_CONTENT_BOX = "flex flex-col border-border-primary bg-elevation-elevation-0 shadow-strong";
1890
2003
  var SHEET_SIDE_CLASSES = {
1891
2004
  right: "inset-y-0 right-0 h-full w-[800px] max-w-[calc(100vw-var(--sheet-edge-gap))] border-l data-[state=open]:slide-in-from-right data-[state=closed]:slide-out-to-right",
1892
2005
  left: "inset-y-0 left-0 h-full w-[800px] max-w-[calc(100vw-var(--sheet-edge-gap))] border-r data-[state=open]:slide-in-from-left data-[state=closed]:slide-out-to-left",
1893
2006
  top: "inset-x-0 top-0 w-full h-auto max-h-[calc(100vh-var(--sheet-edge-gap))] border-b data-[state=open]:slide-in-from-top data-[state=closed]:slide-out-to-top",
1894
2007
  bottom: "inset-x-0 bottom-0 w-full h-auto max-h-[calc(100vh-var(--sheet-edge-gap))] border-t data-[state=open]:slide-in-from-bottom data-[state=closed]:slide-out-to-bottom"
1895
2008
  };
2009
+ var SHEET_RESIZE_SIDE_CLASSES = {
2010
+ right: "inset-y-0 right-0 max-w-[calc(100vw-var(--sheet-edge-gap))] data-[state=open]:slide-in-from-right data-[state=closed]:slide-out-to-right",
2011
+ left: "inset-y-0 left-0 max-w-[calc(100vw-var(--sheet-edge-gap))] data-[state=open]:slide-in-from-left data-[state=closed]:slide-out-to-left",
2012
+ top: "inset-x-0 top-0 max-h-[calc(100vh-var(--sheet-edge-gap))] data-[state=open]:slide-in-from-top data-[state=closed]:slide-out-to-top",
2013
+ bottom: "inset-x-0 bottom-0 max-h-[calc(100vh-var(--sheet-edge-gap))] data-[state=open]:slide-in-from-bottom data-[state=closed]:slide-out-to-bottom"
2014
+ };
1896
2015
  var SheetContext = React.createContext({ side: "right" });
1897
2016
  var SheetRoot = (props) => /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, { ...props });
1898
2017
  var Sheet = SheetRoot;
@@ -1917,7 +2036,9 @@ Sheet.Overlay = React.forwardRef(
1917
2036
  )
1918
2037
  );
1919
2038
  Sheet.Content = React.forwardRef(
1920
- ({ className, children, side = "right", onInteractOutside, ...props }, ref) => {
2039
+ ({ className, children, side = "right", resizable = false, onInteractOutside, ...props }, ref) => {
2040
+ const resizeOptions = typeof resizable === "object" ? resizable : { use: resizable };
2041
+ const isResizable = resizeOptions.use ?? true;
1921
2042
  const shouldPreventDismissForSelect = (target) => {
1922
2043
  const isSelectOpen = Boolean(
1923
2044
  document.querySelector('[data-radix-select-content][data-state="open"]')
@@ -1945,17 +2066,14 @@ Sheet.Content = React.forwardRef(
1945
2066
  {
1946
2067
  ref,
1947
2068
  className: utils.cn(
1948
- // 공통 스타일 (Modal Content 토큰, radius 제외)
1949
- "fixed z-50 flex flex-col border-border-primary bg-elevation-elevation-0 shadow-strong data-[state=open]:duration-300 data-[state=closed]:duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1950
- // 가장자리 여백 CSS 변수 정의 (side 클래스의 max-w/max-h가 참조)
2069
+ SHEET_CONTENT_BASE,
1951
2070
  SHEET_EDGE_GAP,
1952
- // side 위치/크기/슬라이드
1953
- SHEET_SIDE_CLASSES[side],
2071
+ isResizable ? SHEET_RESIZE_SIDE_CLASSES[side] : utils.cn(SHEET_CONTENT_BOX, SHEET_SIDE_CLASSES[side]),
1954
2072
  className
1955
2073
  ),
1956
2074
  ...props,
1957
2075
  onInteractOutside: handleInteractOutside,
1958
- children
2076
+ children: isResizable ? /* @__PURE__ */ jsxRuntime.jsx(SheetResizableBox, { side, options: resizeOptions, children }) : children
1959
2077
  }
1960
2078
  )
1961
2079
  ] }) });