@vmscloud/moz-ui-grid-react 0.1.25 → 0.1.27

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/MozGrid.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ReactNode, ComponentType } from 'react';
2
- import { GridChrome, WrapperExtras, MozGridCoreProps, WrapperToolItemsProps } from '@vmscloud/moz-ui-grid-wrapper';
2
+ import { GridChrome, WrapperExtras, MozGridCoreProps, WrapperToolItemsProps, WrapperOptionMenuItemsProps } from '@vmscloud/moz-ui-grid-wrapper';
3
3
  import { DataMutationEvent, PureSheet, ScrollEndReachedPayload, ScrollPayload } from '@vmscloud/moz-ui-grid-core';
4
- import { CellSlotProps, HeaderSlotProps, EditorSlotProps } from './types/slots';
4
+ import { CellSlotProps, HeaderSlotProps, EditorSlotProps, GroupSlotProps } from './types/slots';
5
5
  /**
6
6
  * MozGrid — vanilla GridChrome(@vmscloud/moz-ui-grid-wrapper) 위임 React 어댑터.
7
7
  *
@@ -21,11 +21,22 @@ export type MozGridProps = WrapperExtras & {
21
21
  cellTemplates?: Record<string, ComponentType<CellSlotProps>>;
22
22
  headerTemplates?: Record<string, ComponentType<HeaderSlotProps>>;
23
23
  editorTemplates?: Record<string, ComponentType<EditorSlotProps>>;
24
+ /**
25
+ * 그룹 헤더 템플릿 (Vue `<GroupTemplate>` 대응). 보이는 그룹 배너 안에 마운트되어 라벨·건수·집계
26
+ * 자리를 대체한다(펼침/접힘 토글 버튼은 core 가 유지). 템플릿 요소의 이벤트(툴팁 등)는 그대로 받는다.
27
+ */
28
+ groupTemplate?: ComponentType<GroupSlotProps>;
24
29
  toolLeft?: ReactNode;
25
30
  /** tool-items 슬롯 — 정적 ReactNode 또는 {disabled,hasItem} 받는 render-prop (Vue 스코프 슬롯 대응). */
26
31
  toolItems?: ReactNode | ((props: WrapperToolItemsProps) => ReactNode);
27
32
  toolBottom?: ReactNode;
28
33
  optionPopup?: ReactNode;
34
+ /**
35
+ * option-menu-items 슬롯 — 보기 설정(톱니바퀴) 메뉴 Main 화면 끝에 넣는 소비처 항목.
36
+ * 정적 ReactNode 또는 `{ close, mode }` 받는 render-prop (Vue `#option-menu-items="{ close, mode }"` 대응).
37
+ * 메뉴를 닫았다 열어도 같은 React 인스턴스(상태)가 유지되며, MozGrid 가 렌더될 때마다 최신 값으로 다시 그린다.
38
+ */
39
+ optionMenuItems?: ReactNode | ((props: WrapperOptionMenuItemsProps) => ReactNode);
29
40
  notification?: ReactNode;
30
41
  footer?: ReactNode;
31
42
  /** 빈 상태 customState 영역 (Vue `#empty-state` 슬롯 대응) */
@@ -87,11 +98,22 @@ export declare const MozGrid: import('react').ForwardRefExoticComponent<WrapperE
87
98
  cellTemplates?: Record<string, ComponentType<CellSlotProps>>;
88
99
  headerTemplates?: Record<string, ComponentType<HeaderSlotProps>>;
89
100
  editorTemplates?: Record<string, ComponentType<EditorSlotProps>>;
101
+ /**
102
+ * 그룹 헤더 템플릿 (Vue `<GroupTemplate>` 대응). 보이는 그룹 배너 안에 마운트되어 라벨·건수·집계
103
+ * 자리를 대체한다(펼침/접힘 토글 버튼은 core 가 유지). 템플릿 요소의 이벤트(툴팁 등)는 그대로 받는다.
104
+ */
105
+ groupTemplate?: ComponentType<GroupSlotProps>;
90
106
  toolLeft?: ReactNode;
91
107
  /** tool-items 슬롯 — 정적 ReactNode 또는 {disabled,hasItem} 받는 render-prop (Vue 스코프 슬롯 대응). */
92
108
  toolItems?: ReactNode | ((props: WrapperToolItemsProps) => ReactNode);
93
109
  toolBottom?: ReactNode;
94
110
  optionPopup?: ReactNode;
111
+ /**
112
+ * option-menu-items 슬롯 — 보기 설정(톱니바퀴) 메뉴 Main 화면 끝에 넣는 소비처 항목.
113
+ * 정적 ReactNode 또는 `{ close, mode }` 받는 render-prop (Vue `#option-menu-items="{ close, mode }"` 대응).
114
+ * 메뉴를 닫았다 열어도 같은 React 인스턴스(상태)가 유지되며, MozGrid 가 렌더될 때마다 최신 값으로 다시 그린다.
115
+ */
116
+ optionMenuItems?: ReactNode | ((props: WrapperOptionMenuItemsProps) => ReactNode);
95
117
  notification?: ReactNode;
96
118
  footer?: ReactNode;
97
119
  /** 빈 상태 customState 영역 (Vue `#empty-state` 슬롯 대응) */
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var e=Object.defineProperty,t=(t,o,n)=>((t,o,n)=>o in t?e(t,o,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[o]=n)(t,"symbol"!=typeof o?o+"":o,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),n=require("react"),r=require("@vmscloud/moz-ui-grid-wrapper"),u=require("react-dom/client");class s{constructor(){t(this,"instances",new Map),t(this,"contextWrapper",null),t(this,"lifecycleRoots",new WeakMap)}setContextWrapper(e){this.contextWrapper=e}mount(e,t,o,n={}){let r=this.instances.get(e);if(r&&r.container!==t){const t=r;queueMicrotask(()=>t.root.unmount()),this.instances.delete(e),r=void 0}if(r)return r.component=o,r.props={...n},void this.render(r);r={root:u.createRoot(t),container:t,component:o,props:{...n}},this.instances.set(e,r),this.render(r)}mountInstance(e,t,o){const r=this.lifecycleRoots.get(e);if(r)try{r.unmount()}catch{}const s=u.createRoot(e);this.lifecycleRoots.set(e,s);const i=e=>{const o=n.createElement(t,e);s.render(this.contextWrapper?this.contextWrapper(o):o)};return i(o),{update:e=>i(e),destroy:()=>{queueMicrotask(()=>{this.lifecycleRoots.get(e)===s&&(s.unmount(),this.lifecycleRoots.delete(e))})}}}updateProps(e,t){const o=this.instances.get(e);o&&(o.props={...o.props,...t},this.render(o))}unmount(e){const t=this.instances.get(e);t&&(queueMicrotask(()=>t.root.unmount()),this.instances.delete(e))}unmountByPrefix(e){for(const t of Array.from(this.instances.keys()))t.startsWith(e)&&this.unmount(t)}unmountAll(){for(const[,e]of this.instances)queueMicrotask(()=>e.root.unmount());this.instances.clear()}get size(){return this.instances.size}has(e){return this.instances.has(e)}render(e){const t=n.createElement(e.component,e.props),o=this.contextWrapper?this.contextWrapper(t):t;e.root.render(o)}}const i=n.createContext(null);function c(){return n.useContext(i)}const l=n.createContext({});function a(){const e=n.useContext(l),t=n.useContext(p);return{...e,locale:t??e.locale}}function d({config:e={},children:t}){const n=a(),r={locale:e.locale??n.locale,timeZone:e.timeZone??n.timeZone};return void 0!==r.timeZone&&new Intl.DateTimeFormat("en",{timeZone:r.timeZone}),o.jsx(l.Provider,{value:r,children:o.jsx(p.Provider,{value:r.locale,children:t})})}const p=n.createContext(void 0);function m(e,t,o){return e.map(e=>{const n={...e},r=t.get("cell",e.id);(null==r?void 0:r.component)&&(n.cellRenderer=function(e,t,o){const n=e=>({value:e.value,rowData:e.rowData,columnId:e.columnId,rowId:e.rowId}),r=(e,r)=>{const u=o.mountInstance(e,t,n(r));return{update:e=>(u.update(n(e)),!0),destroy(){u.destroy()}}};return r.__cellRendererKind="lifecycle",r}(e.id,r.component,o));const u=t.get("header",e.id);(null==u?void 0:u.component)&&(n.headerRenderer=function(e,t,o){return n=>{const r=document.createElement("div");r.style.display="contents";const u=`header:${e}`,s={columnId:n.columnId,header:n.header};return o.mount(u,r,t,s),r}}(e.id,u.component,o));const s=t.get("editor",e.id);return(null==s?void 0:s.component)&&(n.editor=function(e,t,o){return{type:"custom",renderer:n=>{const r=document.createElement("div");r.style.display="contents";const u=`editor:${e}`,s={value:n.value,rowData:n.rowData,columnId:e,onCommit:n.onCommit,onCancel:n.onCancel};return o.mount(u,r,t,s),r},destroy:()=>{o.unmount(`editor:${e}`)}}}(e.id,s.component,o)),n})}const g=[["data:changed","onDataChanged"],["row:click","onRowClick"],["row:dblclick","onRowDblclick"],["row:pinned","onRowPinned"],["row:unpinned","onRowUnpinned"],["row:reordered","onRowReordered"],["cell:click","onCellClick"],["cell:dblclick","onCellDblclick"],["cell:change","onCellChange"],["cell:beforeEdit","onCellBeforeEdit"],["cell:editCommitting","onCellEditCommitting"],["cell:editCommitted","onCellEditCommitted"],["cell:tooltip","onCellTooltip"],["selection:changed","onSelectionChanged"],["column:resize","onColumnResize"],["column:reorder","onColumnReorder"],["column:pin","onColumnPin"],["column:visibility","onColumnVisibility"],["sort:changed","onSortChanged"],["header:click","onHeaderClick"],["header:sortClick","onHeaderSortClick"],["header:filterClick","onHeaderFilterClick"],["filter:changed","onFilterChanged"],["scroll","onScroll"],["scroll:endReached","onEndReached"],["undo:stateChange","onUndoStateChange"],["clipboard:copy","onClipboardCopy"],["clipboard:paste","onClipboardPaste"],["validation:changed","onValidationChanged"],["columnGroup:toggle","onColumnGroupToggle"],["contextmenu","onContextMenu"],["rowGroup:toggle","onGroupToggle"],["rowGroup:batchToggle","onGroupBatchToggle"]],f=[["tool-left","toolLeft"],["tool-items","toolItems"],["option-popup","optionPopup"],["tool-bottom","toolBottom"],["notification","notification"],["footer","footer"],["empty-state","emptyStateContent"]],C=n.forwardRef(function(e,t){var u,i;const l=n.useRef(null),d=n.useRef(null),p=n.useRef(null),C=c(),h=n.useRef(C);h.current=C;const x=a(),y=e.locale??(null==(u=e.coreConfig)?void 0:u.locale)??x.locale,v=n.useRef();v.current=(null==(i=e.coreConfig)?void 0:i.timeZone)??x.timeZone;const S=n.useRef(y);S.current=y;const R=n.useRef([]),w=n.useRef({disabled:!0,hasItem:!1}),M=n.useRef(new Set),T=e=>{w.current=e,M.current.forEach(e=>e())},I=n.useRef(e);I.current=e;const b=n.useRef(void 0),F=n.useRef(void 0),P=n.useRef(null),[B,E]=n.useState(0),G=()=>{var e;const t=I.current,o=p.current,n=null==(e=t.coreConfig)?void 0:e.fields;if(o&&n!==b.current){const e=function(){const e=[];function t(e,t){return t?`${e}:${t}`:e}return{register(o){const n=e.findIndex(e=>t(e.type,e.fieldId)===t(o.type,o.fieldId));n>=0?e[n]=o:e.push(o)},unregister(o,n){const r=t(o,n),u=e.findIndex(e=>t(e.type,e.fieldId)===r);u>=0&&e.splice(u,1)},get(o,n){const r=t(o,n);return e.find(e=>t(e.type,e.fieldId)===r)},getAll:t=>e.filter(e=>e.type===t)}}();for(const[o,n]of Object.entries(t.cellTemplates??{}))e.register({type:"cell",fieldId:o,component:n});for(const[o,n]of Object.entries(t.headerTemplates??{}))e.register({type:"header",fieldId:o,component:n});for(const[o,n]of Object.entries(t.editorTemplates??{}))e.register({type:"editor",fieldId:o,component:n});b.current=n,F.current=n?m(n,e,o):void 0}const r={...t.coreConfig??{}},u=F.current;return u&&(r.fields=u),void 0!==S.current&&(r.locale=S.current),r.timeZone=v.current,r},k=()=>{const e=l.current;if(!e)return;const t=new s;t.setContextWrapper(h.current),p.current=t,b.current=void 0,F.current=void 0;const u=new r.GridChrome(e,G(),(e=>{const t=I.current,r={};for(const[u,s]of f)null!=t[s]&&(r[u]=t=>{const r=`slot:${u}`,i="tool-items"===u?()=>{const[,e]=n.useState(0);n.useEffect(()=>{const t=()=>e(e=>e+1);return M.current.add(t),()=>{M.current.delete(t)}},[]);const t=I.current.toolItems;return o.jsx(o.Fragment,{children:("function"==typeof t?t(w.current):t)??null})}:()=>o.jsx(o.Fragment,{children:I.current[s]??null});return e.mount(r,t,i,{}),()=>e.unmount(r)});return{useToolBox:t.useToolBox,useToolBoxSetting:t.useToolBoxSetting,useExtendFooter:t.useExtendFooter,useSummaryFooter:t.useSummaryFooter,useSort:t.useSort,useCustomCell:t.useCustomCell,useContextMenu:t.useContextMenu,useBuiltinTooltip:t.useBuiltinTooltip,usePivot:t.usePivot,usePivotBar:t.usePivotBar,useRowGroupSettings:t.useRowGroupSettings,useFieldSettings:t.useFieldSettings,useFormatSettings:t.useFormatSettings,useLayoutSettings:t.useLayoutSettings,useAggregateSettings:t.useAggregateSettings,useChart:t.useChart,useMultipleChart:t.useMultipleChart,chartIncludeGrandTotal:t.chartIncludeGrandTotal,chartMap:t.chartMap,loading:t.loading,locale:S.current,sourceFields:t.sourceFields,contextMenuConfig:t.contextMenuConfig,emptyState:t.emptyState,slots:r,onToolItemsPropsChange:e=>T(e)}})(t));d.current=u,u.on("data:loaded",()=>{var e,t;return null==(t=(e=I.current).onDataLoaded)?void 0:t.call(e)});const i=u.on.bind(u);for(const[o,n]of g)i(o,e=>{var t,o;return null==(o=(t=I.current)[n])?void 0:o.call(t,e)});R.current.push(u.onConfigChange(()=>{var e,t;const o=I.current.coreConfig;null==(t=(e=I.current).onCoreConfigChange)||t.call(e,u.getCoreConfig(o))}));const c=P.current;P.current=null,u.ready().then(async()=>{var e,t;d.current===u&&(c&&await u.restoreReinitState(c),d.current===u&&(T(u.getToolItemsProps()),null==(t=(e=I.current).onReady)||t.call(e,u.grid,u)))}).catch(e=>{d.current})};n.useEffect(()=>{var e;null==(e=p.current)||e.setContextWrapper(C)},[C]),n.useEffect(()=>(k(),()=>{var e,t;for(const o of R.current)try{o()}catch{}R.current=[],null==(e=d.current)||e.destroy(),d.current=null,null==(t=p.current)||t.unmountAll(),p.current=null}),[B]),n.useEffect(()=>{const e=d.current;if(!e)return;const{reinitRequired:t}=e.reconcileCoreConfig(G());t&&(P.current=e.captureReinitState(),E(e=>e+1))}),n.useEffect(()=>{var t;null==(t=d.current)||t.setUIOptions({useToolBox:e.useToolBox,useToolBoxSetting:e.useToolBoxSetting,useExtendFooter:e.useExtendFooter,useSummaryFooter:e.useSummaryFooter,useSort:e.useSort,useCustomCell:e.useCustomCell,useContextMenu:e.useContextMenu,useBuiltinTooltip:e.useBuiltinTooltip,usePivot:e.usePivot,usePivotBar:e.usePivotBar,useRowGroupSettings:e.useRowGroupSettings,useFieldSettings:e.useFieldSettings,useFormatSettings:e.useFormatSettings,useLayoutSettings:e.useLayoutSettings,useAggregateSettings:e.useAggregateSettings,loading:e.loading})},[e.useToolBox,e.useToolBoxSetting,e.useExtendFooter,e.useSummaryFooter,e.useSort,e.useCustomCell,e.useContextMenu,e.useBuiltinTooltip,e.usePivot,e.usePivotBar,e.useRowGroupSettings,e.useFieldSettings,e.useFormatSettings,e.useLayoutSettings,e.useAggregateSettings,e.loading]),n.useEffect(()=>{var t;null==(t=d.current)||t.setContextMenuConfig(e.contextMenuConfig)},[e.contextMenuConfig]),n.useImperativeHandle(t,()=>new Proxy({},{get(e,t){if("chrome"===t)return d.current;const o=d.current;if(!o)return;const n=o[t];return"function"==typeof n?n.bind(o):n},has:(e,t)=>"chrome"===t||!!d.current&&t in d.current}),[]);const z=e.height,W={height:"number"==typeof z?`${z}px`:z??"100%",width:"100%",overflow:"hidden"};return o.jsx("div",{ref:l,className:"moz-grid-chrome",style:W})});exports.MozContextWrapperContext=i,exports.MozGrid=C,exports.MozGridConfigContext=l,exports.MozGridConfigProvider=d,exports.MozGridLocaleContext=p,exports.MozGridLocaleProvider=function({locale:e,children:t}){return o.jsx(d,{config:{locale:e},children:t})},exports.useMozContextWrapper=c,exports.useMozGridConfig=a,exports.useMozGridLocale=function(){return n.useContext(p)};
1
+ "use strict";var e=Object.defineProperty,t=(t,o,n)=>((t,o,n)=>o in t?e(t,o,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[o]=n)(t,"symbol"!=typeof o?o+"":o,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),n=require("react"),r=require("@vmscloud/moz-ui-grid-wrapper"),u=require("react-dom/client");class s{constructor(){t(this,"instances",new Map),t(this,"contextWrapper",null),t(this,"lifecycleRoots",new WeakMap)}setContextWrapper(e){this.contextWrapper=e}mount(e,t,o,n={}){let r=this.instances.get(e);if(r&&r.container!==t){const t=r;queueMicrotask(()=>t.root.unmount()),this.instances.delete(e),r=void 0}if(r)return r.component=o,r.props={...n},void this.render(r);r={root:u.createRoot(t),container:t,component:o,props:{...n}},this.instances.set(e,r),this.render(r)}mountInstance(e,t,o){const r=this.lifecycleRoots.get(e);if(r)try{r.unmount()}catch{}const s=u.createRoot(e);this.lifecycleRoots.set(e,s);const i=e=>{const o=n.createElement(t,e);s.render(this.contextWrapper?this.contextWrapper(o):o)};return i(o),{update:e=>i(e),destroy:()=>{queueMicrotask(()=>{this.lifecycleRoots.get(e)===s&&(s.unmount(),this.lifecycleRoots.delete(e))})}}}updateProps(e,t){const o=this.instances.get(e);o&&(o.props={...o.props,...t},this.render(o))}unmount(e){const t=this.instances.get(e);t&&(queueMicrotask(()=>t.root.unmount()),this.instances.delete(e))}unmountByPrefix(e){for(const t of Array.from(this.instances.keys()))t.startsWith(e)&&this.unmount(t)}unmountAll(){for(const[,e]of this.instances)queueMicrotask(()=>e.root.unmount());this.instances.clear()}get size(){return this.instances.size}has(e){return this.instances.has(e)}render(e){const t=n.createElement(e.component,e.props),o=this.contextWrapper?this.contextWrapper(t):t;e.root.render(o)}}const i=n.createContext(null);function l(){return n.useContext(i)}const c=n.createContext({});function a(){const e=n.useContext(c),t=n.useContext(p);return{...e,locale:t??e.locale}}function d({config:e={},children:t}){const n=a(),r={locale:e.locale??n.locale,timeZone:e.timeZone??n.timeZone};return void 0!==r.timeZone&&new Intl.DateTimeFormat("en",{timeZone:r.timeZone}),o.jsx(c.Provider,{value:r,children:o.jsx(p.Provider,{value:r.locale,children:t})})}const p=n.createContext(void 0);function f(e,t,o){return e.map(e=>{const n={...e},r=t.get("cell",e.id);(null==r?void 0:r.component)&&(n.cellRenderer=function(e,t,o){const n=e=>({value:e.value,rowData:e.rowData,columnId:e.columnId,rowId:e.rowId}),r=(e,r)=>{const u=o.mountInstance(e,t,n(r));return{update:e=>(u.update(n(e)),!0),destroy(){u.destroy()}}};return r.__cellRendererKind="lifecycle",r}(e.id,r.component,o));const u=t.get("header",e.id);(null==u?void 0:u.component)&&(n.headerRenderer=function(e,t,o){return n=>{const r=document.createElement("div");r.style.display="contents";const u=`header:${e}`,s={columnId:n.columnId,header:n.header};return o.mount(u,r,t,s),r}}(e.id,u.component,o));const s=t.get("editor",e.id);return(null==s?void 0:s.component)&&(n.editor=function(e,t,o){return{type:"custom",renderer:n=>{const r=document.createElement("div");r.style.display="contents";const u=`editor:${e}`,s={value:n.value,rowData:n.rowData,columnId:e,onCommit:n.onCommit,onCancel:n.onCancel};return o.mount(u,r,t,s),r},destroy:()=>{o.unmount(`editor:${e}`)}}}(e.id,s.component,o)),n})}const g="_groupTemplate",m=[["data:changed","onDataChanged"],["row:click","onRowClick"],["row:dblclick","onRowDblclick"],["row:pinned","onRowPinned"],["row:unpinned","onRowUnpinned"],["row:reordered","onRowReordered"],["cell:click","onCellClick"],["cell:dblclick","onCellDblclick"],["cell:change","onCellChange"],["cell:beforeEdit","onCellBeforeEdit"],["cell:editCommitting","onCellEditCommitting"],["cell:editCommitted","onCellEditCommitted"],["cell:tooltip","onCellTooltip"],["selection:changed","onSelectionChanged"],["column:resize","onColumnResize"],["column:reorder","onColumnReorder"],["column:pin","onColumnPin"],["column:visibility","onColumnVisibility"],["sort:changed","onSortChanged"],["header:click","onHeaderClick"],["header:sortClick","onHeaderSortClick"],["header:filterClick","onHeaderFilterClick"],["filter:changed","onFilterChanged"],["scroll","onScroll"],["scroll:endReached","onEndReached"],["undo:stateChange","onUndoStateChange"],["clipboard:copy","onClipboardCopy"],["clipboard:paste","onClipboardPaste"],["validation:changed","onValidationChanged"],["columnGroup:toggle","onColumnGroupToggle"],["contextmenu","onContextMenu"],["rowGroup:toggle","onGroupToggle"],["rowGroup:batchToggle","onGroupBatchToggle"]],C=[["tool-left","toolLeft"],["tool-items","toolItems"],["option-popup","optionPopup"],["tool-bottom","toolBottom"],["notification","notification"],["footer","footer"],["empty-state","emptyStateContent"],["option-menu-items","optionMenuItems"]],h=n.forwardRef(function(e,t){var u,i,c,d,p,h;const v=n.useRef(null),x=n.useRef(null),y=n.useRef(null),S=l(),R=n.useRef(S);R.current=S;const w=a(),b=e.locale??(null==(u=e.coreConfig)?void 0:u.locale)??w.locale,M=n.useRef();M.current=(null==(i=e.coreConfig)?void 0:i.timeZone)??w.timeZone;const F=n.useRef(b);F.current=b;const T=n.useRef([]),I=n.useRef({disabled:!0,hasItem:!1}),E=n.useRef(new Set),P=e=>{I.current=e,E.current.forEach(e=>e())},B=n.useRef(new Set);n.useEffect(()=>{B.current.forEach(e=>e())});const k=n.useRef(e);k.current=e;const G=n.useRef(void 0),z=n.useRef(void 0),j=n.useRef(null),L=n.useRef(new Map),W=n.useRef(null),A=e=>{const t=L.current.get(e);t&&(L.current.delete(e),t.destroy())},D=()=>{var e,t;null==(t=null==(e=W.current)?void 0:e.grid.formatRow)||t.removeHandler(g),W.current=null;for(const o of[...L.current.keys()])A(o)},q=(e,t)=>{const o=k.current.groupTemplate,n=W.current;if(n&&n.grid===e&&n.component===o)return!1;const r=null!==n;return D(),o&&(null==e?void 0:e.formatRow)&&t?(e.formatRow.addHandler(g,e=>{if("group-row"!==e.type)return;const n=e.ctx,r=n.element;if(!r)return;const u={groupKey:n.column,groupValue:n.value,level:n.level,count:n.itemCount,isExpanded:!n.collapsed},s=L.current.get(r);if(s&&r.classList.contains("ps-group-template-host"))return void s.update(u);s&&A(r);const i=t.mountInstance(r,o,u);L.current.set(r,i),r.addEventListener("ps-group-template-dispose",()=>A(r),{once:!0})}),W.current={grid:e,component:o},!0):r},[Z,$]=n.useState(0),H=()=>{var e;const t=k.current,o=y.current,n=null==(e=t.coreConfig)?void 0:e.fields;if(o&&n!==G.current){const e=function(){const e=[];function t(e,t){return t?`${e}:${t}`:e}return{register(o){const n=e.findIndex(e=>t(e.type,e.fieldId)===t(o.type,o.fieldId));n>=0?e[n]=o:e.push(o)},unregister(o,n){const r=t(o,n),u=e.findIndex(e=>t(e.type,e.fieldId)===r);u>=0&&e.splice(u,1)},get(o,n){const r=t(o,n);return e.find(e=>t(e.type,e.fieldId)===r)},getAll:t=>e.filter(e=>e.type===t)}}();for(const[o,n]of Object.entries(t.cellTemplates??{}))e.register({type:"cell",fieldId:o,component:n});for(const[o,n]of Object.entries(t.headerTemplates??{}))e.register({type:"header",fieldId:o,component:n});for(const[o,n]of Object.entries(t.editorTemplates??{}))e.register({type:"editor",fieldId:o,component:n});G.current=n,z.current=n?f(n,e,o):void 0}const r={...t.coreConfig??{}},u=z.current;return u&&(r.fields=u),void 0!==F.current&&(r.locale=F.current),r.timeZone=M.current,r},O=()=>{const e=v.current;if(!e)return;const t=new s;t.setContextWrapper(R.current),y.current=t,G.current=void 0,z.current=void 0;const u=new r.GridChrome(e,H(),(e=>{const t=k.current,r={};for(const[u,s]of C)null!=t[s]&&(r[u]=(t,r)=>{const i=`slot:${u}`,l="tool-items"===u?()=>{const[,e]=n.useState(0);n.useEffect(()=>{const t=()=>e(e=>e+1);return E.current.add(t),()=>{E.current.delete(t)}},[]);const t=k.current.toolItems;return o.jsx(o.Fragment,{children:("function"==typeof t?t(I.current):t)??null})}:"option-menu-items"===u?()=>{const[,e]=n.useState(0);n.useEffect(()=>{const t=()=>e(e=>e+1);return B.current.add(t),()=>{B.current.delete(t)}},[]);const t=k.current.optionMenuItems,u=r.props;return o.jsx(o.Fragment,{children:("function"==typeof t?t(u):t)??null})}:()=>o.jsx(o.Fragment,{children:k.current[s]??null});return e.mount(i,t,l,{}),()=>e.unmount(i)});return{useToolBox:t.useToolBox,useToolBoxSetting:t.useToolBoxSetting,useExtendFooter:t.useExtendFooter,useSummaryFooter:t.useSummaryFooter,useSort:t.useSort,useCustomCell:t.useCustomCell,useContextMenu:t.useContextMenu,useBuiltinTooltip:t.useBuiltinTooltip,usePivot:t.usePivot,usePivotBar:t.usePivotBar,useRowGroupSettings:t.useRowGroupSettings,useFieldSettings:t.useFieldSettings,useFormatSettings:t.useFormatSettings,useLayoutSettings:t.useLayoutSettings,useAggregateSettings:t.useAggregateSettings,toolbarConfig:t.toolbarConfig,useChart:t.useChart,useMultipleChart:t.useMultipleChart,chartIncludeGrandTotal:t.chartIncludeGrandTotal,chartMap:t.chartMap,chartConfig:t.chartConfig,loading:t.loading,locale:F.current,sourceFields:t.sourceFields,contextMenuConfig:t.contextMenuConfig,emptyState:t.emptyState,slots:r,onToolItemsPropsChange:e=>P(e)}})(t));x.current=u,q(u.grid,t),u.on("data:loaded",()=>{var e,t;return null==(t=(e=k.current).onDataLoaded)?void 0:t.call(e)});const i=u.on.bind(u);for(const[o,n]of m)i(o,e=>{var t,o;return null==(o=(t=k.current)[n])?void 0:o.call(t,e)});T.current.push(u.onConfigChange(()=>{var e,t;const o=k.current.coreConfig;null==(t=(e=k.current).onCoreConfigChange)||t.call(e,u.getCoreConfig(o))}));const l=j.current;j.current=null,u.ready().then(async()=>{var e,t;x.current===u&&(l&&await u.restoreReinitState(l),x.current===u&&(P(u.getToolItemsProps()),null==(t=(e=k.current).onReady)||t.call(e,u.grid,u)))}).catch(e=>{x.current})};n.useEffect(()=>{var e;null==(e=y.current)||e.setContextWrapper(S)},[S]),n.useEffect(()=>(O(),()=>{var e,t;for(const o of T.current)try{o()}catch{}T.current=[],D(),null==(e=x.current)||e.destroy(),x.current=null,null==(t=y.current)||t.unmountAll(),y.current=null}),[Z]),n.useEffect(()=>{const e=x.current;if(!e)return;const{reinitRequired:t}=e.reconcileCoreConfig(H());t&&(j.current=e.captureReinitState(),$(e=>e+1))}),n.useEffect(()=>{var e,t;const o=x.current;o&&q(o.grid,y.current)&&(null==(t=null==(e=o.grid)?void 0:e.refresh)||t.call(e))},[e.groupTemplate]);const U=null==(d=null==(c=e.toolbarConfig)?void 0:c.filter)?void 0:d.disabled,V=null==(h=null==(p=e.toolbarConfig)?void 0:p.filter)?void 0:h.hidden;n.useEffect(()=>{var t;null==(t=x.current)||t.setUIOptions({useToolBox:e.useToolBox,useToolBoxSetting:e.useToolBoxSetting,useExtendFooter:e.useExtendFooter,useSummaryFooter:e.useSummaryFooter,useSort:e.useSort,useCustomCell:e.useCustomCell,useContextMenu:e.useContextMenu,useBuiltinTooltip:e.useBuiltinTooltip,usePivot:e.usePivot,usePivotBar:e.usePivotBar,useRowGroupSettings:e.useRowGroupSettings,useFieldSettings:e.useFieldSettings,useFormatSettings:e.useFormatSettings,useLayoutSettings:e.useLayoutSettings,useAggregateSettings:e.useAggregateSettings,toolbarConfig:{filter:{disabled:U,hidden:V}},loading:e.loading})},[e.useToolBox,e.useToolBoxSetting,e.useExtendFooter,e.useSummaryFooter,e.useSort,e.useCustomCell,e.useContextMenu,e.useBuiltinTooltip,e.usePivot,e.usePivotBar,e.useRowGroupSettings,e.useFieldSettings,e.useFormatSettings,e.useLayoutSettings,e.useAggregateSettings,U,V,e.loading]),n.useEffect(()=>{var t;null==(t=x.current)||t.setContextMenuConfig(e.contextMenuConfig)},[e.contextMenuConfig]);const _=e.chartConfig,K=e=>e?e.join("\0"):"";n.useEffect(()=>{var t,o;null==(o=null==(t=x.current)?void 0:t.setChartConfig)||o.call(t,e.chartConfig)},[null==_?void 0:_.transformData,null==_?void 0:_.xAxisLabelFormatter,null==_?void 0:_.accumulate,K(null==_?void 0:_.categoryFieldsExclude),K(null==_?void 0:_.xAxisFieldsExclude),K(null==_?void 0:_.valueFields),null==_?void 0:_.container]),n.useImperativeHandle(t,()=>new Proxy({},{get(e,t){if("chrome"===t)return x.current;const o=x.current;if(!o)return;const n=o[t];return"function"==typeof n?n.bind(o):n},has:(e,t)=>"chrome"===t||!!x.current&&t in x.current}),[]);const N=e.height,J={height:"number"==typeof N?`${N}px`:N??"100%",width:"100%",overflow:"hidden"};return o.jsx("div",{ref:v,className:"moz-grid-chrome",style:J})});exports.MozContextWrapperContext=i,exports.MozGrid=h,exports.MozGridConfigContext=c,exports.MozGridConfigProvider=d,exports.MozGridLocaleContext=p,exports.MozGridLocaleProvider=function({locale:e,children:t}){return o.jsx(d,{config:{locale:e},children:t})},exports.useMozContextWrapper=l,exports.useMozGridConfig=a,exports.useMozGridLocale=function(){return n.useContext(p)};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { MozGrid, type MozGridProps, type MozGridHandle } from './MozGrid';
2
+ export type { CellSlotProps, HeaderSlotProps, EditorSlotProps, GroupSlotProps } from './types/slots';
2
3
  export { MozGridLocaleContext, MozGridLocaleProvider, useMozGridLocale } from './locale/MozGridLocaleContext';
3
4
  export type { MozGridLocaleProviderProps } from './locale/MozGridLocaleContext';
4
5
  export { MozGridConfigContext, MozGridConfigProvider, useMozGridConfig } from './locale/MozGridLocaleContext';
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { jsx, Fragment } from "react/jsx-runtime";
5
- import { createElement, createContext, useContext, forwardRef, useRef, useState, useEffect, useImperativeHandle } from "react";
5
+ import { createElement, createContext, useContext, forwardRef, useRef, useEffect, useState, useImperativeHandle } from "react";
6
6
  import { GridChrome } from "@vmscloud/moz-ui-grid-wrapper";
7
7
  import { createRoot } from "react-dom/client";
8
8
  class ReactRenderer {
@@ -247,6 +247,9 @@ function createEditorConfig(fieldId, Component, renderer) {
247
247
  }
248
248
  };
249
249
  }
250
+ const GROUP_TEMPLATE_DISPOSE_EVENT = "ps-group-template-dispose";
251
+ const GROUP_TEMPLATE_HOST_CLASS = "ps-group-template-host";
252
+ const GROUP_TEMPLATE_HOOK_ID = "_groupTemplate";
250
253
  const EVENT_CALLBACKS = [
251
254
  ["data:changed", "onDataChanged"],
252
255
  ["row:click", "onRowClick"],
@@ -289,10 +292,11 @@ const SLOT_PROP_MAP = [
289
292
  ["tool-bottom", "toolBottom"],
290
293
  ["notification", "notification"],
291
294
  ["footer", "footer"],
292
- ["empty-state", "emptyStateContent"]
295
+ ["empty-state", "emptyStateContent"],
296
+ ["option-menu-items", "optionMenuItems"]
293
297
  ];
294
298
  const MozGrid = forwardRef(function MozGrid2(props, ref) {
295
- var _a, _b;
299
+ var _a, _b, _c, _d, _e, _f;
296
300
  const hostRef = useRef(null);
297
301
  const chromeRef = useRef(null);
298
302
  const rendererRef = useRef(null);
@@ -312,11 +316,61 @@ const MozGrid = forwardRef(function MozGrid2(props, ref) {
312
316
  toolItemsPropsRef.current = p;
313
317
  toolItemsSubsRef.current.forEach((fn) => fn());
314
318
  };
319
+ const optionMenuItemsSubsRef = useRef(/* @__PURE__ */ new Set());
320
+ useEffect(() => {
321
+ optionMenuItemsSubsRef.current.forEach((fn) => fn());
322
+ });
315
323
  const propsRef = useRef(props);
316
324
  propsRef.current = props;
317
325
  const lastRawFieldsRef = useRef(void 0);
318
326
  const lastBuiltFieldsRef = useRef(void 0);
319
327
  const pendingRestoreRef = useRef(null);
328
+ const groupInstancesRef = useRef(/* @__PURE__ */ new Map());
329
+ const groupRegistrationRef = useRef(null);
330
+ const disposeGroupTemplate = (container) => {
331
+ const instance = groupInstancesRef.current.get(container);
332
+ if (!instance) return;
333
+ groupInstancesRef.current.delete(container);
334
+ instance.destroy();
335
+ };
336
+ const unregisterGroupTemplate = () => {
337
+ var _a2, _b2;
338
+ (_b2 = (_a2 = groupRegistrationRef.current) == null ? void 0 : _a2.grid.formatRow) == null ? void 0 : _b2.removeHandler(GROUP_TEMPLATE_HOOK_ID);
339
+ groupRegistrationRef.current = null;
340
+ for (const container of [...groupInstancesRef.current.keys()]) disposeGroupTemplate(container);
341
+ };
342
+ const syncGroupTemplate = (grid, renderer) => {
343
+ const component = propsRef.current.groupTemplate;
344
+ const current = groupRegistrationRef.current;
345
+ if (current && current.grid === grid && current.component === component) return false;
346
+ const hadRegistration = current !== null;
347
+ unregisterGroupTemplate();
348
+ if (!component || !(grid == null ? void 0 : grid.formatRow) || !renderer) return hadRegistration;
349
+ grid.formatRow.addHandler(GROUP_TEMPLATE_HOOK_ID, (info) => {
350
+ if (info.type !== "group-row") return;
351
+ const ctx = info.ctx;
352
+ const container = ctx.element;
353
+ if (!container) return;
354
+ const slotProps = {
355
+ groupKey: ctx.column,
356
+ groupValue: ctx.value,
357
+ level: ctx.level,
358
+ count: ctx.itemCount,
359
+ isExpanded: !ctx.collapsed
360
+ };
361
+ const existing = groupInstancesRef.current.get(container);
362
+ if (existing && container.classList.contains(GROUP_TEMPLATE_HOST_CLASS)) {
363
+ existing.update(slotProps);
364
+ return;
365
+ }
366
+ if (existing) disposeGroupTemplate(container);
367
+ const instance = renderer.mountInstance(container, component, slotProps);
368
+ groupInstancesRef.current.set(container, instance);
369
+ container.addEventListener(GROUP_TEMPLATE_DISPOSE_EVENT, () => disposeGroupTemplate(container), { once: true });
370
+ });
371
+ groupRegistrationRef.current = { grid, component };
372
+ return true;
373
+ };
320
374
  const [mountTick, setMountTick] = useState(0);
321
375
  const buildCoreConfig = () => {
322
376
  var _a2;
@@ -349,7 +403,7 @@ const MozGrid = forwardRef(function MozGrid2(props, ref) {
349
403
  const slotMap = {};
350
404
  for (const [slotName, propKey] of SLOT_PROP_MAP) {
351
405
  if (p[propKey] != null) {
352
- slotMap[slotName] = (container) => {
406
+ slotMap[slotName] = (container, ctx) => {
353
407
  const key = `slot:${slotName}`;
354
408
  const SlotComp = slotName === "tool-items" ? () => {
355
409
  const [, force] = useState(0);
@@ -362,6 +416,18 @@ const MozGrid = forwardRef(function MozGrid2(props, ref) {
362
416
  }, []);
363
417
  const ti = propsRef.current.toolItems;
364
418
  return /* @__PURE__ */ jsx(Fragment, { children: (typeof ti === "function" ? ti(toolItemsPropsRef.current) : ti) ?? null });
419
+ } : slotName === "option-menu-items" ? () => {
420
+ const [, force] = useState(0);
421
+ useEffect(() => {
422
+ const fn = () => force((x) => x + 1);
423
+ optionMenuItemsSubsRef.current.add(fn);
424
+ return () => {
425
+ optionMenuItemsSubsRef.current.delete(fn);
426
+ };
427
+ }, []);
428
+ const omi = propsRef.current.optionMenuItems;
429
+ const scope = ctx.props;
430
+ return /* @__PURE__ */ jsx(Fragment, { children: (typeof omi === "function" ? omi(scope) : omi) ?? null });
365
431
  } : () => /* @__PURE__ */ jsx(Fragment, { children: propsRef.current[propKey] ?? null });
366
432
  renderer.mount(key, container, SlotComp, {});
367
433
  return () => renderer.unmount(key);
@@ -384,10 +450,12 @@ const MozGrid = forwardRef(function MozGrid2(props, ref) {
384
450
  useFormatSettings: p.useFormatSettings,
385
451
  useLayoutSettings: p.useLayoutSettings,
386
452
  useAggregateSettings: p.useAggregateSettings,
453
+ toolbarConfig: p.toolbarConfig,
387
454
  useChart: p.useChart,
388
455
  useMultipleChart: p.useMultipleChart,
389
456
  chartIncludeGrandTotal: p.chartIncludeGrandTotal,
390
457
  chartMap: p.chartMap,
458
+ chartConfig: p.chartConfig,
391
459
  loading: p.loading,
392
460
  locale: resolvedLocaleRef.current,
393
461
  sourceFields: p.sourceFields,
@@ -407,6 +475,7 @@ const MozGrid = forwardRef(function MozGrid2(props, ref) {
407
475
  lastBuiltFieldsRef.current = void 0;
408
476
  const chrome = new GridChrome(host, buildCoreConfig(), buildChromeOptions(renderer));
409
477
  chromeRef.current = chrome;
478
+ syncGroupTemplate(chrome.grid, renderer);
410
479
  chrome.on("data:loaded", () => {
411
480
  var _a2, _b2;
412
481
  return (_b2 = (_a2 = propsRef.current).onDataLoaded) == null ? void 0 : _b2.call(_a2);
@@ -454,6 +523,7 @@ const MozGrid = forwardRef(function MozGrid2(props, ref) {
454
523
  }
455
524
  }
456
525
  chromeUnsubsRef.current = [];
526
+ unregisterGroupTemplate();
457
527
  (_a2 = chromeRef.current) == null ? void 0 : _a2.destroy();
458
528
  chromeRef.current = null;
459
529
  (_b2 = rendererRef.current) == null ? void 0 : _b2.unmountAll();
@@ -469,6 +539,14 @@ const MozGrid = forwardRef(function MozGrid2(props, ref) {
469
539
  setMountTick((t) => t + 1);
470
540
  }
471
541
  });
542
+ useEffect(() => {
543
+ var _a2, _b2;
544
+ const chrome = chromeRef.current;
545
+ if (!chrome) return;
546
+ if (syncGroupTemplate(chrome.grid, rendererRef.current)) void ((_b2 = (_a2 = chrome.grid) == null ? void 0 : _a2.refresh) == null ? void 0 : _b2.call(_a2));
547
+ }, [props.groupTemplate]);
548
+ const tbFilterDisabled = (_d = (_c = props.toolbarConfig) == null ? void 0 : _c.filter) == null ? void 0 : _d.disabled;
549
+ const tbFilterHidden = (_f = (_e = props.toolbarConfig) == null ? void 0 : _e.filter) == null ? void 0 : _f.hidden;
472
550
  useEffect(() => {
473
551
  var _a2;
474
552
  (_a2 = chromeRef.current) == null ? void 0 : _a2.setUIOptions({
@@ -487,6 +565,8 @@ const MozGrid = forwardRef(function MozGrid2(props, ref) {
487
565
  useFormatSettings: props.useFormatSettings,
488
566
  useLayoutSettings: props.useLayoutSettings,
489
567
  useAggregateSettings: props.useAggregateSettings,
568
+ // 툴바 필터 버튼 — 매 렌더 새 객체 리터럴이어도 deps 는 primitive 값이라 같은 값이면 재실행 없음.
569
+ toolbarConfig: { filter: { disabled: tbFilterDisabled, hidden: tbFilterHidden } },
490
570
  loading: props.loading
491
571
  });
492
572
  }, [
@@ -505,12 +585,29 @@ const MozGrid = forwardRef(function MozGrid2(props, ref) {
505
585
  props.useFormatSettings,
506
586
  props.useLayoutSettings,
507
587
  props.useAggregateSettings,
588
+ tbFilterDisabled,
589
+ tbFilterHidden,
508
590
  props.loading
509
591
  ]);
510
592
  useEffect(() => {
511
593
  var _a2;
512
594
  (_a2 = chromeRef.current) == null ? void 0 : _a2.setContextMenuConfig(props.contextMenuConfig);
513
595
  }, [props.contextMenuConfig]);
596
+ const cc = props.chartConfig;
597
+ const listKey = (a) => a ? a.join("\0") : "";
598
+ useEffect(() => {
599
+ var _a2, _b2;
600
+ (_b2 = (_a2 = chromeRef.current) == null ? void 0 : _a2.setChartConfig) == null ? void 0 : _b2.call(_a2, props.chartConfig);
601
+ }, [
602
+ cc == null ? void 0 : cc.transformData,
603
+ cc == null ? void 0 : cc.xAxisLabelFormatter,
604
+ cc == null ? void 0 : cc.accumulate,
605
+ listKey(cc == null ? void 0 : cc.categoryFieldsExclude),
606
+ listKey(cc == null ? void 0 : cc.xAxisFieldsExclude),
607
+ listKey(cc == null ? void 0 : cc.valueFields),
608
+ // 외부 차트 영역(요소 identity 또는 선택자 문자열) — 바뀔 때만 재배치.
609
+ cc == null ? void 0 : cc.container
610
+ ]);
514
611
  useImperativeHandle(ref, () => new Proxy({}, {
515
612
  get(_t, p) {
516
613
  if (p === "chrome") return chromeRef.current;